[go: nahoru, domu]

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
17package android.support.v7.preference;
18
19import android.content.Context;
20import android.content.res.TypedArray;
21import android.os.Parcel;
22import android.os.Parcelable;
23import android.text.TextUtils;
24import android.util.AttributeSet;
25import android.view.View;
26import 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 */
33public 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
41    public TwoStatePreference(
42            Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
43        super(context, attrs, defStyleAttr, defStyleRes);
44    }
45
46    public TwoStatePreference(Context context, AttributeSet attrs, int defStyleAttr) {
47        this(context, attrs, defStyleAttr, 0);
48    }
49
50    public TwoStatePreference(Context context, AttributeSet attrs) {
51        this(context, attrs, 0);
52    }
53
54    public TwoStatePreference(Context context) {
55        this(context, null);
56    }
57
58    @Override
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     */
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     */
92    public boolean isChecked() {
93        return mChecked;
94    }
95
96    @Override
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
175    public void setDisableDependentsState(boolean disableDependentsState) {
176        mDisableDependentsState = disableDependentsState;
177    }
178
179    @Override
180    protected Object onGetDefaultValue(TypedArray a, int index) {
181        return a.getBoolean(index, false);
182    }
183
184    @Override
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     */
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     */
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
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
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
262        public SavedState(Parcel source) {
263            super(source);
264            checked = source.readInt() == 1;
265        }
266
267        @Override
268        public void writeToParcel(Parcel dest, int flags) {
269            super.writeToParcel(dest, flags);
270            dest.writeInt(checked ? 1 : 0);
271        }
272
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