• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 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 android.preference;
18 
19 import android.annotation.StringRes;
20 import android.compat.annotation.UnsupportedAppUsage;
21 import android.content.Context;
22 import android.content.SharedPreferences;
23 import android.content.res.TypedArray;
24 import android.os.Parcel;
25 import android.os.Parcelable;
26 import android.text.TextUtils;
27 import android.util.AttributeSet;
28 import android.view.View;
29 import android.widget.TextView;
30 
31 /**
32  * Common base class for preferences that have two selectable states, persist a
33  * boolean value in SharedPreferences, and may have dependent preferences that are
34  * enabled/disabled based on the current state.
35  *
36  * @deprecated Use the <a href="{@docRoot}jetpack/androidx.html">AndroidX</a>
37  *      <a href="{@docRoot}reference/androidx/preference/package-summary.html">
38  *      Preference Library</a> for consistent behavior across all devices. For more information on
39  *      using the AndroidX Preference Library see
40  *      <a href="{@docRoot}guide/topics/ui/settings.html">Settings</a>.
41  */
42 @Deprecated
43 public abstract class TwoStatePreference extends Preference {
44 
45     private CharSequence mSummaryOn;
46     private CharSequence mSummaryOff;
47     boolean mChecked;
48     private boolean mCheckedSet;
49     private boolean mDisableDependentsState;
50 
TwoStatePreference( Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)51     public TwoStatePreference(
52             Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
53         super(context, attrs, defStyleAttr, defStyleRes);
54     }
55 
TwoStatePreference(Context context, AttributeSet attrs, int defStyleAttr)56     public TwoStatePreference(Context context, AttributeSet attrs, int defStyleAttr) {
57         this(context, attrs, defStyleAttr, 0);
58     }
59 
TwoStatePreference(Context context, AttributeSet attrs)60     public TwoStatePreference(Context context, AttributeSet attrs) {
61         this(context, attrs, 0);
62     }
63 
TwoStatePreference(Context context)64     public TwoStatePreference(Context context) {
65         this(context, null);
66     }
67 
68     @Override
onClick()69     protected void onClick() {
70         super.onClick();
71 
72         final boolean newValue = !isChecked();
73         if (callChangeListener(newValue)) {
74             setChecked(newValue);
75         }
76     }
77 
78     /**
79      * Sets the checked state and saves it to the {@link SharedPreferences}.
80      *
81      * @param checked The checked state.
82      */
setChecked(boolean checked)83     public void setChecked(boolean checked) {
84         // Always persist/notify the first time; don't assume the field's default of false.
85         final boolean changed = mChecked != checked;
86         if (changed || !mCheckedSet) {
87             mChecked = checked;
88             mCheckedSet = true;
89             persistBoolean(checked);
90             if (changed) {
91                 notifyDependencyChange(shouldDisableDependents());
92                 notifyChanged();
93             }
94         }
95     }
96 
97     /**
98      * Returns the checked state.
99      *
100      * @return The checked state.
101      */
isChecked()102     public boolean isChecked() {
103         return mChecked;
104     }
105 
106     @Override
shouldDisableDependents()107     public boolean shouldDisableDependents() {
108         boolean shouldDisable = mDisableDependentsState ? mChecked : !mChecked;
109         return shouldDisable || super.shouldDisableDependents();
110     }
111 
112     /**
113      * Sets the summary to be shown when checked.
114      *
115      * @param summary The summary to be shown when checked.
116      */
setSummaryOn(CharSequence summary)117     public void setSummaryOn(CharSequence summary) {
118         mSummaryOn = summary;
119         if (isChecked()) {
120             notifyChanged();
121         }
122     }
123 
124     /**
125      * @see #setSummaryOn(CharSequence)
126      * @param summaryResId The summary as a resource.
127      */
setSummaryOn(@tringRes int summaryResId)128     public void setSummaryOn(@StringRes int summaryResId) {
129         setSummaryOn(getContext().getString(summaryResId));
130     }
131 
132     /**
133      * Returns the summary to be shown when checked.
134      * @return The summary.
135      */
getSummaryOn()136     public CharSequence getSummaryOn() {
137         return mSummaryOn;
138     }
139 
140     /**
141      * Sets the summary to be shown when unchecked.
142      *
143      * @param summary The summary to be shown when unchecked.
144      */
setSummaryOff(CharSequence summary)145     public void setSummaryOff(CharSequence summary) {
146         mSummaryOff = summary;
147         if (!isChecked()) {
148             notifyChanged();
149         }
150     }
151 
152     /**
153      * @see #setSummaryOff(CharSequence)
154      * @param summaryResId The summary as a resource.
155      */
setSummaryOff(@tringRes int summaryResId)156     public void setSummaryOff(@StringRes int summaryResId) {
157         setSummaryOff(getContext().getString(summaryResId));
158     }
159 
160     /**
161      * Returns the summary to be shown when unchecked.
162      * @return The summary.
163      */
getSummaryOff()164     public CharSequence getSummaryOff() {
165         return mSummaryOff;
166     }
167 
168     /**
169      * Returns whether dependents are disabled when this preference is on ({@code true})
170      * or when this preference is off ({@code false}).
171      *
172      * @return Whether dependents are disabled when this preference is on ({@code true})
173      *         or when this preference is off ({@code false}).
174      */
getDisableDependentsState()175     public boolean getDisableDependentsState() {
176         return mDisableDependentsState;
177     }
178 
179     /**
180      * Sets whether dependents are disabled when this preference is on ({@code true})
181      * or when this preference is off ({@code false}).
182      *
183      * @param disableDependentsState The preference state that should disable dependents.
184      */
setDisableDependentsState(boolean disableDependentsState)185     public void setDisableDependentsState(boolean disableDependentsState) {
186         mDisableDependentsState = disableDependentsState;
187     }
188 
189     @Override
onGetDefaultValue(TypedArray a, int index)190     protected Object onGetDefaultValue(TypedArray a, int index) {
191         return a.getBoolean(index, false);
192     }
193 
194     @Override
onSetInitialValue(boolean restoreValue, Object defaultValue)195     protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
196         setChecked(restoreValue ? getPersistedBoolean(mChecked)
197                 : (Boolean) defaultValue);
198     }
199 
200     /**
201      * Sync a summary view contained within view's subhierarchy with the correct summary text.
202      * @param view View where a summary should be located
203      */
204     @UnsupportedAppUsage
syncSummaryView(View view)205     void syncSummaryView(View view) {
206         // Sync the summary view
207         TextView summaryView = (TextView) view.findViewById(com.android.internal.R.id.summary);
208         if (summaryView != null) {
209             boolean useDefaultSummary = true;
210             if (mChecked && !TextUtils.isEmpty(mSummaryOn)) {
211                 summaryView.setText(mSummaryOn);
212                 useDefaultSummary = false;
213             } else if (!mChecked && !TextUtils.isEmpty(mSummaryOff)) {
214                 summaryView.setText(mSummaryOff);
215                 useDefaultSummary = false;
216             }
217 
218             if (useDefaultSummary) {
219                 final CharSequence summary = getSummary();
220                 if (!TextUtils.isEmpty(summary)) {
221                     summaryView.setText(summary);
222                     useDefaultSummary = false;
223                 }
224             }
225 
226             int newVisibility = View.GONE;
227             if (!useDefaultSummary) {
228                 // Someone has written to it
229                 newVisibility = View.VISIBLE;
230             }
231             if (newVisibility != summaryView.getVisibility()) {
232                 summaryView.setVisibility(newVisibility);
233             }
234         }
235     }
236 
237     @Override
onSaveInstanceState()238     protected Parcelable onSaveInstanceState() {
239         final Parcelable superState = super.onSaveInstanceState();
240         if (isPersistent()) {
241             // No need to save instance state since it's persistent
242             return superState;
243         }
244 
245         final SavedState myState = new SavedState(superState);
246         myState.checked = isChecked();
247         return myState;
248     }
249 
250     @Override
onRestoreInstanceState(Parcelable state)251     protected void onRestoreInstanceState(Parcelable state) {
252         if (state == null || !state.getClass().equals(SavedState.class)) {
253             // Didn't save state for us in onSaveInstanceState
254             super.onRestoreInstanceState(state);
255             return;
256         }
257 
258         SavedState myState = (SavedState) state;
259         super.onRestoreInstanceState(myState.getSuperState());
260         setChecked(myState.checked);
261     }
262 
263     static class SavedState extends BaseSavedState {
264         boolean checked;
265 
SavedState(Parcel source)266         public SavedState(Parcel source) {
267             super(source);
268             checked = source.readInt() == 1;
269         }
270 
271         @Override
writeToParcel(Parcel dest, int flags)272         public void writeToParcel(Parcel dest, int flags) {
273             super.writeToParcel(dest, flags);
274             dest.writeInt(checked ? 1 : 0);
275         }
276 
SavedState(Parcelable superState)277         public SavedState(Parcelable superState) {
278             super(superState);
279         }
280 
281         public static final @android.annotation.NonNull Parcelable.Creator<SavedState> CREATOR =
282                 new Parcelable.Creator<SavedState>() {
283             public SavedState createFromParcel(Parcel in) {
284                 return new SavedState(in);
285             }
286 
287             public SavedState[] newArray(int size) {
288                 return new SavedState[size];
289             }
290         };
291     }
292 }
293