Home | History | Annotate | Download | only in preference
      1 /*
      2  * Copyright 2018 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 
     29 import androidx.annotation.RestrictTo;
     30 import androidx.appcompat.widget.SwitchCompat;
     31 import androidx.core.content.res.TypedArrayUtils;
     32 
     33 /**
     34 * A {@link 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 SwitchPreferenceCompat 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             SwitchPreferenceCompat.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 SwitchPreferenceCompat(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.SwitchPreferenceCompat, defStyleAttr, defStyleRes);
     84 
     85         setSummaryOn(TypedArrayUtils.getString(a, R.styleable.SwitchPreferenceCompat_summaryOn,
     86                 R.styleable.SwitchPreferenceCompat_android_summaryOn));
     87 
     88         setSummaryOff(TypedArrayUtils.getString(a, R.styleable.SwitchPreferenceCompat_summaryOff,
     89                 R.styleable.SwitchPreferenceCompat_android_summaryOff));
     90 
     91         setSwitchTextOn(TypedArrayUtils.getString(a,
     92                 R.styleable.SwitchPreferenceCompat_switchTextOn,
     93                 R.styleable.SwitchPreferenceCompat_android_switchTextOn));
     94 
     95         setSwitchTextOff(TypedArrayUtils.getString(a,
     96                 R.styleable.SwitchPreferenceCompat_switchTextOff,
     97                 R.styleable.SwitchPreferenceCompat_android_switchTextOff));
     98 
     99         setDisableDependentsState(TypedArrayUtils.getBoolean(a,
    100                 R.styleable.SwitchPreferenceCompat_disableDependentsState,
    101                 R.styleable.SwitchPreferenceCompat_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 SwitchPreferenceCompat(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 SwitchPreferenceCompat(Context context, AttributeSet attrs) {
    126         this(context, attrs, R.attr.switchPreferenceCompatStyle);
    127     }
    128 
    129     /**
    130      * Construct a new SwitchPreference with default style options.
    131      *
    132      * @param context The Context that will style this preference
    133      */
    134     public SwitchPreferenceCompat(Context context) {
    135         this(context, null);
    136     }
    137 
    138     @Override
    139     public void onBindViewHolder(PreferenceViewHolder holder) {
    140         super.onBindViewHolder(holder);
    141         View switchView = holder.findViewById(R.id.switchWidget);
    142         syncSwitchView(switchView);
    143         syncSummaryView(holder);
    144     }
    145 
    146     /**
    147      * Set the text displayed on the switch widget in the on state.
    148      * This should be a very short string; one word if possible.
    149      *
    150      * @param onText Text to display in the on state
    151      */
    152     public void setSwitchTextOn(CharSequence onText) {
    153         mSwitchOn = onText;
    154         notifyChanged();
    155     }
    156 
    157     /**
    158      * Set the text displayed on the switch widget in the off state.
    159      * This should be a very short string; one word if possible.
    160      *
    161      * @param offText Text to display in the off state
    162      */
    163     public void setSwitchTextOff(CharSequence offText) {
    164         mSwitchOff = offText;
    165         notifyChanged();
    166     }
    167 
    168     /**
    169      * Set the text displayed on the switch widget in the on state.
    170      * This should be a very short string; one word if possible.
    171      *
    172      * @param resId The text as a string resource ID
    173      */
    174     public void setSwitchTextOn(int resId) {
    175         setSwitchTextOn(getContext().getString(resId));
    176     }
    177 
    178     /**
    179      * Set the text displayed on the switch widget in the off state.
    180      * This should be a very short string; one word if possible.
    181      *
    182      * @param resId The text as a string resource ID
    183      */
    184     public void setSwitchTextOff(int resId) {
    185         setSwitchTextOff(getContext().getString(resId));
    186     }
    187 
    188     /**
    189      * @return The text that will be displayed on the switch widget in the on state
    190      */
    191     public CharSequence getSwitchTextOn() {
    192         return mSwitchOn;
    193     }
    194 
    195     /**
    196      * @return The text that will be displayed on the switch widget in the off state
    197      */
    198     public CharSequence getSwitchTextOff() {
    199         return mSwitchOff;
    200     }
    201 
    202     /**
    203      * @hide
    204      */
    205     @RestrictTo(LIBRARY_GROUP)
    206     @Override
    207     protected void performClick(View view) {
    208         super.performClick(view);
    209         syncViewIfAccessibilityEnabled(view);
    210     }
    211 
    212     private void syncViewIfAccessibilityEnabled(View view) {
    213         AccessibilityManager accessibilityManager = (AccessibilityManager)
    214                 getContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
    215         if (!accessibilityManager.isEnabled()) {
    216             return;
    217         }
    218 
    219         View switchView = view.findViewById(R.id.switchWidget);
    220         syncSwitchView(switchView);
    221 
    222         View summaryView = view.findViewById(android.R.id.summary);
    223         syncSummaryView(summaryView);
    224     }
    225 
    226     private void syncSwitchView(View view) {
    227         if (view instanceof SwitchCompat) {
    228             final SwitchCompat switchView = (SwitchCompat) view;
    229             switchView.setOnCheckedChangeListener(null);
    230         }
    231         if (view instanceof Checkable) {
    232             ((Checkable) view).setChecked(mChecked);
    233         }
    234         if (view instanceof SwitchCompat) {
    235             final SwitchCompat switchView = (SwitchCompat) view;
    236             switchView.setTextOn(mSwitchOn);
    237             switchView.setTextOff(mSwitchOff);
    238             switchView.setOnCheckedChangeListener(mListener);
    239         }
    240     }
    241 }
    242