SwitchPreferenceCompat.java revision c67647d83261aad33d42309c52aa75e05ea9daf7
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.support.v4.content.res.TypedArrayUtils;
22import android.support.v7.widget.SwitchCompat;
23import android.util.AttributeSet;
24import android.view.View;
25import android.view.accessibility.AccessibilityManager;
26import android.widget.Checkable;
27import android.widget.CompoundButton;
28
29/**
30* A {@link Preference} that provides a two-state toggleable option.
31* <p>
32* This preference will store a boolean into the SharedPreferences.
33*
34* @attr ref android.R.styleable#SwitchPreference_summaryOff
35* @attr ref android.R.styleable#SwitchPreference_summaryOn
36* @attr ref android.R.styleable#SwitchPreference_switchTextOff
37* @attr ref android.R.styleable#SwitchPreference_switchTextOn
38* @attr ref android.R.styleable#SwitchPreference_disableDependentsState
39*/
40public class SwitchPreferenceCompat extends TwoStatePreference {
41    private final Listener mListener = new Listener();
42
43    // Switch text for on and off states
44    private CharSequence mSwitchOn;
45    private CharSequence mSwitchOff;
46
47    private class Listener implements CompoundButton.OnCheckedChangeListener {
48        @Override
49        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
50            if (!callChangeListener(isChecked)) {
51                // Listener didn't like it, change it back.
52                // CompoundButton will make sure we don't recurse.
53                buttonView.setChecked(!isChecked);
54                return;
55            }
56
57            SwitchPreferenceCompat.this.setChecked(isChecked);
58        }
59    }
60
61    /**
62     * Construct a new SwitchPreference with the given style options.
63     *
64     * @param context The Context that will style this preference
65     * @param attrs Style attributes that differ from the default
66     * @param defStyleAttr An attribute in the current theme that contains a
67     *        reference to a style resource that supplies default values for
68     *        the view. Can be 0 to not look for defaults.
69     * @param defStyleRes A resource identifier of a style resource that
70     *        supplies default values for the view, used only if
71     *        defStyleAttr is 0 or can not be found in the theme. Can be 0
72     *        to not look for defaults.
73     */
74    public SwitchPreferenceCompat(Context context, AttributeSet attrs, int defStyleAttr,
75            int defStyleRes) {
76        super(context, attrs, defStyleAttr, defStyleRes);
77
78        TypedArray a = context.obtainStyledAttributes(attrs,
79                R.styleable.SwitchPreferenceCompat, defStyleAttr, defStyleRes);
80
81        setSummaryOn(TypedArrayUtils.getString(a, R.styleable.SwitchPreferenceCompat_summaryOn,
82                R.styleable.SwitchPreferenceCompat_android_summaryOn));
83
84        setSummaryOff(TypedArrayUtils.getString(a, R.styleable.SwitchPreferenceCompat_summaryOff,
85                R.styleable.SwitchPreferenceCompat_android_summaryOff));
86
87        setSwitchTextOn(TypedArrayUtils.getString(a,
88                R.styleable.SwitchPreferenceCompat_switchTextOn,
89                R.styleable.SwitchPreferenceCompat_android_switchTextOn));
90
91        setSwitchTextOff(TypedArrayUtils.getString(a,
92                R.styleable.SwitchPreferenceCompat_switchTextOff,
93                R.styleable.SwitchPreferenceCompat_android_switchTextOff));
94
95        setDisableDependentsState(TypedArrayUtils.getBoolean(a,
96                R.styleable.SwitchPreferenceCompat_disableDependentsState,
97                R.styleable.SwitchPreferenceCompat_android_disableDependentsState, false));
98
99        a.recycle();
100    }
101
102    /**
103     * Construct a new SwitchPreference with the given style options.
104     *
105     * @param context The Context that will style this preference
106     * @param attrs Style attributes that differ from the default
107     * @param defStyleAttr An attribute in the current theme that contains a
108     *        reference to a style resource that supplies default values for
109     *        the view. Can be 0 to not look for defaults.
110     */
111    public SwitchPreferenceCompat(Context context, AttributeSet attrs, int defStyleAttr) {
112        this(context, attrs, defStyleAttr, 0);
113    }
114
115    /**
116     * Construct a new SwitchPreference with the given style options.
117     *
118     * @param context The Context that will style this preference
119     * @param attrs Style attributes that differ from the default
120     */
121    public SwitchPreferenceCompat(Context context, AttributeSet attrs) {
122        this(context, attrs, R.attr.switchPreferenceCompatStyle);
123    }
124
125    /**
126     * Construct a new SwitchPreference with default style options.
127     *
128     * @param context The Context that will style this preference
129     */
130    public SwitchPreferenceCompat(Context context) {
131        this(context, null);
132    }
133
134    @Override
135    public void onBindViewHolder(PreferenceViewHolder holder) {
136        super.onBindViewHolder(holder);
137        View switchView = holder.findViewById(R.id.switchWidget);
138        syncSwitchView(switchView);
139        syncSummaryView(holder);
140    }
141
142    /**
143     * Set the text displayed on the switch widget in the on state.
144     * This should be a very short string; one word if possible.
145     *
146     * @param onText Text to display in the on state
147     */
148    public void setSwitchTextOn(CharSequence onText) {
149        mSwitchOn = onText;
150        notifyChanged();
151    }
152
153    /**
154     * Set the text displayed on the switch widget in the off state.
155     * This should be a very short string; one word if possible.
156     *
157     * @param offText Text to display in the off state
158     */
159    public void setSwitchTextOff(CharSequence offText) {
160        mSwitchOff = offText;
161        notifyChanged();
162    }
163
164    /**
165     * Set the text displayed on the switch widget in the on state.
166     * This should be a very short string; one word if possible.
167     *
168     * @param resId The text as a string resource ID
169     */
170    public void setSwitchTextOn(int resId) {
171        setSwitchTextOn(getContext().getString(resId));
172    }
173
174    /**
175     * Set the text displayed on the switch widget in the off state.
176     * This should be a very short string; one word if possible.
177     *
178     * @param resId The text as a string resource ID
179     */
180    public void setSwitchTextOff(int resId) {
181        setSwitchTextOff(getContext().getString(resId));
182    }
183
184    /**
185     * @return The text that will be displayed on the switch widget in the on state
186     */
187    public CharSequence getSwitchTextOn() {
188        return mSwitchOn;
189    }
190
191    /**
192     * @return The text that will be displayed on the switch widget in the off state
193     */
194    public CharSequence getSwitchTextOff() {
195        return mSwitchOff;
196    }
197
198    /**
199     * @hide
200     */
201    @Override
202    protected void performClick(View view) {
203        super.performClick(view);
204        syncViewIfAccessibilityEnabled(view);
205    }
206
207    private void syncViewIfAccessibilityEnabled(View view) {
208        AccessibilityManager accessibilityManager = (AccessibilityManager)
209                getContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
210        if (!accessibilityManager.isEnabled()) {
211            return;
212        }
213
214        View switchView = view.findViewById(R.id.switchWidget);
215        syncSwitchView(switchView);
216
217        View summaryView = view.findViewById(android.R.id.summary);
218        syncSummaryView(summaryView);
219    }
220
221    private void syncSwitchView(View view) {
222        if (view instanceof SwitchCompat) {
223            final SwitchCompat switchView = (SwitchCompat) view;
224            switchView.setOnCheckedChangeListener(null);
225        }
226        if (view instanceof Checkable) {
227            ((Checkable) view).setChecked(mChecked);
228        }
229        if (view instanceof SwitchCompat) {
230            final SwitchCompat switchView = (SwitchCompat) view;
231            switchView.setTextOn(mSwitchOn);
232            switchView.setTextOff(mSwitchOff);
233            switchView.setOnCheckedChangeListener(mListener);
234        }
235    }
236}
237