1 /* 2 * Copyright (C) 2021 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.settings.widget; 18 19 import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; 20 21 import android.content.Context; 22 import android.content.res.TypedArray; 23 import android.text.TextUtils; 24 import android.util.AttributeSet; 25 import android.widget.Switch; 26 27 import androidx.core.content.res.TypedArrayUtils; 28 import androidx.preference.PreferenceViewHolder; 29 import androidx.preference.TwoStatePreference; 30 31 import com.android.settings.R; 32 import com.android.settings.widget.SettingsMainSwitchBar.OnBeforeCheckedChangeListener; 33 import com.android.settingslib.RestrictedPreferenceHelper; 34 import com.android.settingslib.widget.OnMainSwitchChangeListener; 35 36 import java.util.ArrayList; 37 import java.util.List; 38 39 /** 40 * SettingsMainSwitchPreference is a Preference with a customized Switch. 41 * This component is used as the main switch of the page 42 * to enable or disable the prefereces on the page. 43 */ 44 public class SettingsMainSwitchPreference extends TwoStatePreference implements 45 OnMainSwitchChangeListener { 46 47 private final List<OnBeforeCheckedChangeListener> mBeforeCheckedChangeListeners = 48 new ArrayList<>(); 49 private final List<OnMainSwitchChangeListener> mSwitchChangeListeners = new ArrayList<>(); 50 51 private SettingsMainSwitchBar mMainSwitchBar; 52 private CharSequence mTitle; 53 private EnforcedAdmin mEnforcedAdmin; 54 private RestrictedPreferenceHelper mRestrictedHelper; 55 SettingsMainSwitchPreference(Context context)56 public SettingsMainSwitchPreference(Context context) { 57 super(context); 58 init(context, null); 59 } 60 SettingsMainSwitchPreference(Context context, AttributeSet attrs)61 public SettingsMainSwitchPreference(Context context, AttributeSet attrs) { 62 super(context, attrs); 63 init(context, attrs); 64 } 65 SettingsMainSwitchPreference(Context context, AttributeSet attrs, int defStyleAttr)66 public SettingsMainSwitchPreference(Context context, AttributeSet attrs, int defStyleAttr) { 67 super(context, attrs, defStyleAttr); 68 init(context, attrs); 69 } 70 SettingsMainSwitchPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)71 public SettingsMainSwitchPreference(Context context, AttributeSet attrs, int defStyleAttr, 72 int defStyleRes) { 73 super(context, attrs, defStyleAttr, defStyleRes); 74 init(context, attrs); 75 } 76 77 @Override onBindViewHolder(PreferenceViewHolder holder)78 public void onBindViewHolder(PreferenceViewHolder holder) { 79 super.onBindViewHolder(holder); 80 81 holder.setDividerAllowedAbove(false); 82 holder.setDividerAllowedBelow(false); 83 84 if (mRestrictedHelper != null) { 85 mEnforcedAdmin = mRestrictedHelper.checkRestrictionEnforced(); 86 } 87 mMainSwitchBar = (SettingsMainSwitchBar) holder.findViewById(R.id.main_switch_bar); 88 initMainSwitchBar(); 89 if (isVisible()) { 90 mMainSwitchBar.show(); 91 if (mMainSwitchBar.isChecked() != isChecked()) { 92 setChecked(isChecked()); 93 } 94 registerListenerToSwitchBar(); 95 } else { 96 mMainSwitchBar.hide(); 97 } 98 } 99 init(Context context, AttributeSet attrs)100 private void init(Context context, AttributeSet attrs) { 101 setLayoutResource(R.layout.preference_widget_main_switch); 102 mSwitchChangeListeners.add(this); 103 104 if (attrs != null) { 105 final TypedArray a = context.obtainStyledAttributes(attrs, 106 androidx.preference.R.styleable.Preference, 0/*defStyleAttr*/, 107 0/*defStyleRes*/); 108 final CharSequence title = TypedArrayUtils.getText(a, 109 androidx.preference.R.styleable.Preference_title, 110 androidx.preference.R.styleable.Preference_android_title); 111 if (!TextUtils.isEmpty(title)) { 112 setTitle(title.toString()); 113 } 114 a.recycle(); 115 116 mRestrictedHelper = new RestrictedPreferenceHelper(context, this, attrs); 117 } 118 } 119 120 @Override setChecked(boolean checked)121 public void setChecked(boolean checked) { 122 super.setChecked(checked); 123 if (mMainSwitchBar != null) { 124 mMainSwitchBar.setChecked(checked); 125 } 126 } 127 128 /** 129 * Return the SettingsMainSwitchBar 130 */ getSwitchBar()131 public final SettingsMainSwitchBar getSwitchBar() { 132 return mMainSwitchBar; 133 } 134 135 @Override setTitle(CharSequence title)136 public void setTitle(CharSequence title) { 137 mTitle = title; 138 if (mMainSwitchBar != null) { 139 mMainSwitchBar.setTitle(mTitle); 140 } 141 } 142 143 @Override onSwitchChanged(Switch switchView, boolean isChecked)144 public void onSwitchChanged(Switch switchView, boolean isChecked) { 145 super.setChecked(isChecked); 146 } 147 148 /** 149 * Show the MainSwitchBar 150 */ show()151 public void show() { 152 setVisible(true); 153 if (mMainSwitchBar != null) { 154 mMainSwitchBar.show(); 155 } 156 } 157 158 /** 159 * Hide the MainSwitchBar 160 */ hide()161 public void hide() { 162 setVisible(false); 163 if (mMainSwitchBar != null) { 164 mMainSwitchBar.hide(); 165 } 166 } 167 168 /** 169 * Returns if the MainSwitchBar is visible. 170 */ isShowing()171 public boolean isShowing() { 172 if (mMainSwitchBar != null) { 173 return mMainSwitchBar.isShowing(); 174 } 175 return false; 176 } 177 178 /** 179 * Update the status of switch but doesn't notify the mOnBeforeListener. 180 */ setCheckedInternal(boolean checked)181 public void setCheckedInternal(boolean checked) { 182 super.setChecked(checked); 183 if (mMainSwitchBar != null) { 184 mMainSwitchBar.setCheckedInternal(checked); 185 } 186 } 187 188 /** 189 * Enable or disable the text and switch. 190 */ setSwitchBarEnabled(boolean enabled)191 public void setSwitchBarEnabled(boolean enabled) { 192 setEnabled(enabled); 193 if (mMainSwitchBar != null) { 194 mMainSwitchBar.setEnabled(enabled); 195 } 196 } 197 198 /** 199 * Set the OnBeforeCheckedChangeListener. 200 */ setOnBeforeCheckedChangeListener(OnBeforeCheckedChangeListener listener)201 public void setOnBeforeCheckedChangeListener(OnBeforeCheckedChangeListener listener) { 202 if (mMainSwitchBar == null) { 203 mBeforeCheckedChangeListeners.add(listener); 204 } else { 205 mMainSwitchBar.setOnBeforeCheckedChangeListener(listener); 206 } 207 } 208 209 /** 210 * Adds a listener for switch changes 211 */ addOnSwitchChangeListener(OnMainSwitchChangeListener listener)212 public void addOnSwitchChangeListener(OnMainSwitchChangeListener listener) { 213 if (mMainSwitchBar == null) { 214 mSwitchChangeListeners.add(listener); 215 } else { 216 mMainSwitchBar.addOnSwitchChangeListener(listener); 217 } 218 } 219 220 /** 221 * Remove a listener for switch changes 222 */ removeOnSwitchChangeListener(OnMainSwitchChangeListener listener)223 public void removeOnSwitchChangeListener(OnMainSwitchChangeListener listener) { 224 if (mMainSwitchBar == null) { 225 mSwitchChangeListeners.remove(listener); 226 } else { 227 mMainSwitchBar.removeOnSwitchChangeListener(listener); 228 } 229 } 230 231 /** 232 * If admin is not null, disables the text and switch but keeps the view clickable. 233 * Otherwise, calls setEnabled which will enables the entire view including 234 * the text and switch. 235 */ setDisabledByAdmin(EnforcedAdmin admin)236 public void setDisabledByAdmin(EnforcedAdmin admin) { 237 mEnforcedAdmin = admin; 238 if (mMainSwitchBar != null) { 239 mMainSwitchBar.setDisabledByAdmin(mEnforcedAdmin); 240 } 241 } 242 initMainSwitchBar()243 private void initMainSwitchBar() { 244 if (mMainSwitchBar != null) { 245 mMainSwitchBar.setTitle(mTitle); 246 mMainSwitchBar.setDisabledByAdmin(mEnforcedAdmin); 247 } 248 } 249 registerListenerToSwitchBar()250 private void registerListenerToSwitchBar() { 251 for (OnBeforeCheckedChangeListener listener : mBeforeCheckedChangeListeners) { 252 mMainSwitchBar.setOnBeforeCheckedChangeListener(listener); 253 } 254 for (OnMainSwitchChangeListener listener : mSwitchChangeListeners) { 255 mMainSwitchBar.addOnSwitchChangeListener(listener); 256 } 257 mBeforeCheckedChangeListeners.clear(); 258 mSwitchChangeListeners.clear(); 259 } 260 } 261