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