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