1 /*
2  * Copyright (C) 2020 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.util.AttributeSet;
22 import android.widget.Switch;
23 
24 import androidx.preference.PreferenceViewHolder;
25 import androidx.preference.TwoStatePreference;
26 
27 import java.util.ArrayList;
28 import java.util.List;
29 
30 /**
31  * MainSwitchPreference is a Preference with a customized Switch.
32  * This component is used as the main switch of the page
33  * to enable or disable the prefereces on the page.
34  */
35 public class MainSwitchPreference extends TwoStatePreference implements OnMainSwitchChangeListener {
36 
37     private final List<OnMainSwitchChangeListener> mSwitchChangeListeners = new ArrayList<>();
38 
39     private MainSwitchBar mMainSwitchBar;
40 
MainSwitchPreference(Context context)41     public MainSwitchPreference(Context context) {
42         super(context);
43         init(context, null);
44     }
45 
MainSwitchPreference(Context context, AttributeSet attrs)46     public MainSwitchPreference(Context context, AttributeSet attrs) {
47         super(context, attrs);
48         init(context, attrs);
49     }
50 
MainSwitchPreference(Context context, AttributeSet attrs, int defStyleAttr)51     public MainSwitchPreference(Context context, AttributeSet attrs, int defStyleAttr) {
52         super(context, attrs, defStyleAttr);
53         init(context, attrs);
54     }
55 
MainSwitchPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)56     public MainSwitchPreference(Context context, AttributeSet attrs, int defStyleAttr,
57             int defStyleRes) {
58         super(context, attrs, defStyleAttr, defStyleRes);
59         init(context, attrs);
60     }
61 
62     @Override
onBindViewHolder(PreferenceViewHolder holder)63     public void onBindViewHolder(PreferenceViewHolder holder) {
64         super.onBindViewHolder(holder);
65 
66         holder.setDividerAllowedAbove(false);
67         holder.setDividerAllowedBelow(false);
68 
69         mMainSwitchBar = (MainSwitchBar) holder.findViewById(R.id.settingslib_main_switch_bar);
70         // To support onPreferenceChange callback, it needs to call callChangeListener() when
71         // MainSwitchBar is clicked.
72         mMainSwitchBar.setOnClickListener((view) -> callChangeListener(isChecked()));
73         setIconSpaceReserved(isIconSpaceReserved());
74         updateStatus(isChecked());
75         registerListenerToSwitchBar();
76     }
77 
init(Context context, AttributeSet attrs)78     private void init(Context context, AttributeSet attrs) {
79         setLayoutResource(R.layout.settingslib_main_switch_layout);
80         mSwitchChangeListeners.add(this);
81         if (attrs != null) {
82             final TypedArray a = context.obtainStyledAttributes(attrs,
83                     androidx.preference.R.styleable.Preference, 0 /*defStyleAttr*/,
84                     0 /*defStyleRes*/);
85             final CharSequence title = a.getText(
86                     androidx.preference.R.styleable.Preference_android_title);
87             setTitle(title);
88 
89             final boolean bIconSpaceReserved = a.getBoolean(
90                     androidx.preference.R.styleable.Preference_android_iconSpaceReserved, true);
91             setIconSpaceReserved(bIconSpaceReserved);
92             a.recycle();
93         }
94     }
95 
96     @Override
setChecked(boolean checked)97     public void setChecked(boolean checked) {
98         super.setChecked(checked);
99         if (mMainSwitchBar != null && mMainSwitchBar.isChecked() != checked) {
100             mMainSwitchBar.setChecked(checked);
101         }
102     }
103 
104     @Override
setTitle(CharSequence title)105     public void setTitle(CharSequence title) {
106         super.setTitle(title);
107         if (mMainSwitchBar != null) {
108             mMainSwitchBar.setTitle(title);
109         }
110     }
111 
112     @Override
setIconSpaceReserved(boolean iconSpaceReserved)113     public void setIconSpaceReserved(boolean iconSpaceReserved) {
114         super.setIconSpaceReserved(iconSpaceReserved);
115         if (mMainSwitchBar != null) {
116             mMainSwitchBar.setIconSpaceReserved(iconSpaceReserved);
117         }
118     }
119 
120     @Override
onSwitchChanged(Switch switchView, boolean isChecked)121     public void onSwitchChanged(Switch switchView, boolean isChecked) {
122         super.setChecked(isChecked);
123     }
124 
125     /**
126      * Update the switch status of preference
127      */
updateStatus(boolean checked)128     public void updateStatus(boolean checked) {
129         setChecked(checked);
130         if (mMainSwitchBar != null) {
131             mMainSwitchBar.setTitle(getTitle());
132             mMainSwitchBar.show();
133         }
134     }
135 
136     /**
137      * Adds a listener for switch changes
138      */
addOnSwitchChangeListener(OnMainSwitchChangeListener listener)139     public void addOnSwitchChangeListener(OnMainSwitchChangeListener listener) {
140         if (!mSwitchChangeListeners.contains(listener)) {
141             mSwitchChangeListeners.add(listener);
142         }
143 
144         if (mMainSwitchBar != null) {
145             mMainSwitchBar.addOnSwitchChangeListener(listener);
146         }
147     }
148 
149     /**
150      * Remove a listener for switch changes
151      */
removeOnSwitchChangeListener(OnMainSwitchChangeListener listener)152     public void removeOnSwitchChangeListener(OnMainSwitchChangeListener listener) {
153         mSwitchChangeListeners.remove(listener);
154         if (mMainSwitchBar != null) {
155             mMainSwitchBar.removeOnSwitchChangeListener(listener);
156         }
157     }
158 
registerListenerToSwitchBar()159     private void registerListenerToSwitchBar() {
160         for (OnMainSwitchChangeListener listener : mSwitchChangeListeners) {
161             mMainSwitchBar.addOnSwitchChangeListener(listener);
162         }
163     }
164 }
165