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