1 /* 2 * Copyright (C) 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.settingslib.widget; 18 19 import android.content.Context; 20 import android.content.res.TypedArray; 21 import android.graphics.drawable.Drawable; 22 import android.util.AttributeSet; 23 import android.util.TypedValue; 24 import android.view.Gravity; 25 import android.view.View; 26 import android.widget.Button; 27 import android.widget.LinearLayout; 28 29 import androidx.annotation.GravityInt; 30 import androidx.preference.Preference; 31 import androidx.preference.PreferenceViewHolder; 32 33 /** 34 * A preference handled a button 35 */ 36 public class ButtonPreference extends Preference { 37 38 private static final int ICON_SIZE = 24; 39 40 private View.OnClickListener mClickListener; 41 private Button mButton; 42 private CharSequence mTitle; 43 private Drawable mIcon; 44 @GravityInt 45 private int mGravity; 46 47 /** 48 * Constructs a new LayoutPreference with the given context's theme, the supplied 49 * attribute set, and default style attribute. 50 * 51 * @param context The Context the view is running in, through which it can 52 * access the current theme, resources, etc. 53 * @param attrs The attributes of the XML tag that is inflating the view. 54 * @param defStyleAttr An attribute in the current theme that contains a 55 * reference to a style resource that supplies default 56 * values for the view. Can be 0 to not look for 57 * defaults. 58 */ ButtonPreference(Context context, AttributeSet attrs, int defStyleAttr)59 public ButtonPreference(Context context, AttributeSet attrs, int defStyleAttr) { 60 super(context, attrs, defStyleAttr); 61 init(context, attrs, defStyleAttr); 62 } 63 64 /** 65 * Constructs a new LayoutPreference with the given context's theme and the supplied 66 * attribute set. 67 * 68 * @param context The Context the view is running in, through which it can 69 * access the current theme, resources, etc. 70 * @param attrs The attributes of the XML tag that is inflating the view. 71 */ ButtonPreference(Context context, AttributeSet attrs)72 public ButtonPreference(Context context, AttributeSet attrs) { 73 this(context, attrs, 0 /* defStyleAttr */); 74 } 75 76 /** 77 * Constructs a new LayoutPreference with the given context's theme and a customized view. 78 * 79 * @param context The Context the view is running in, through which it can 80 * access the current theme, resources, etc. 81 */ ButtonPreference(Context context)82 public ButtonPreference(Context context) { 83 this(context, null); 84 } 85 init(Context context, AttributeSet attrs, int defStyleAttr)86 private void init(Context context, AttributeSet attrs, int defStyleAttr) { 87 setLayoutResource(R.layout.settingslib_button_layout); 88 89 if (attrs != null) { 90 TypedArray a = context.obtainStyledAttributes(attrs, 91 androidx.preference.R.styleable.Preference, defStyleAttr, 92 0 /*defStyleRes*/); 93 mTitle = a.getText( 94 androidx.preference.R.styleable.Preference_android_title); 95 mIcon = a.getDrawable( 96 androidx.preference.R.styleable.Preference_android_icon); 97 a.recycle(); 98 99 a = context.obtainStyledAttributes(attrs, 100 R.styleable.ButtonPreference, defStyleAttr, 101 0 /*defStyleRes*/); 102 mGravity = a.getInt(R.styleable.ButtonPreference_android_gravity, Gravity.START); 103 a.recycle(); 104 } 105 } 106 107 @Override onBindViewHolder(PreferenceViewHolder holder)108 public void onBindViewHolder(PreferenceViewHolder holder) { 109 mButton = (Button) holder.findViewById(R.id.settingslib_button); 110 setTitle(mTitle); 111 setIcon(mIcon); 112 setGravity(mGravity); 113 setOnClickListener(mClickListener); 114 115 if (mButton != null) { 116 final boolean selectable = isSelectable(); 117 mButton.setFocusable(selectable); 118 mButton.setClickable(selectable); 119 120 mButton.setEnabled(isEnabled()); 121 } 122 123 holder.setDividerAllowedAbove(false); 124 holder.setDividerAllowedBelow(false); 125 } 126 127 @Override setTitle(CharSequence title)128 public void setTitle(CharSequence title) { 129 mTitle = title; 130 if (mButton != null) { 131 mButton.setText(title); 132 } 133 } 134 getTitle()135 @Override public CharSequence getTitle() { 136 return mTitle; 137 } 138 139 @Override setIcon(Drawable icon)140 public void setIcon(Drawable icon) { 141 mIcon = icon; 142 if (mButton == null || icon == null) { 143 return; 144 } 145 //get pixel from dp 146 int size = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, ICON_SIZE, 147 getContext().getResources().getDisplayMetrics()); 148 icon.setBounds(0, 0, size, size); 149 150 //set drawableStart 151 mButton.setCompoundDrawablesRelativeWithIntrinsicBounds(icon, null/* top */, null/* end */, 152 null/* bottom */); 153 } 154 155 @Override setEnabled(boolean enabled)156 public void setEnabled(boolean enabled) { 157 super.setEnabled(enabled); 158 if (mButton != null) { 159 mButton.setEnabled(enabled); 160 } 161 } 162 163 /** 164 * Return Button 165 */ getButton()166 public Button getButton() { 167 return mButton; 168 } 169 170 171 /** 172 * Set a listener for button click 173 */ setOnClickListener(View.OnClickListener listener)174 public void setOnClickListener(View.OnClickListener listener) { 175 mClickListener = listener; 176 if (mButton != null) { 177 mButton.setOnClickListener(listener); 178 } 179 } 180 181 /** 182 * Set the gravity of button 183 * 184 * @param gravity The {@link Gravity} supported CENTER_HORIZONTAL 185 * and the default value is START 186 */ setGravity(@ravityInt int gravity)187 public void setGravity(@GravityInt int gravity) { 188 if (gravity == Gravity.CENTER_HORIZONTAL || gravity == Gravity.CENTER_VERTICAL 189 || gravity == Gravity.CENTER) { 190 mGravity = Gravity.CENTER_HORIZONTAL; 191 } else { 192 mGravity = Gravity.START; 193 } 194 195 if (mButton != null) { 196 LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) mButton.getLayoutParams(); 197 lp.gravity = mGravity; 198 mButton.setLayoutParams(lp); 199 } 200 } 201 } 202