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.core.content.res.TypedArrayUtils; 31 32 /** 33 * A {@link Preference} that provides checkbox widget 34 * functionality. 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:disableDependentsState 41 */ 42 public class CheckBoxPreference extends TwoStatePreference { 43 private final Listener mListener = new Listener(); 44 45 private class Listener implements CompoundButton.OnCheckedChangeListener { 46 @Override 47 public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 48 if (!callChangeListener(isChecked)) { 49 // Listener didn't like it, change it back. 50 // CompoundButton will make sure we don't recurse. 51 buttonView.setChecked(!isChecked); 52 return; 53 } 54 CheckBoxPreference.this.setChecked(isChecked); 55 } 56 } 57 58 public CheckBoxPreference(Context context, AttributeSet attrs, int defStyleAttr) { 59 this(context, attrs, defStyleAttr, 0); 60 } 61 62 public CheckBoxPreference( 63 Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { 64 super(context, attrs, defStyleAttr, defStyleRes); 65 66 final TypedArray a = context.obtainStyledAttributes(attrs, 67 R.styleable.CheckBoxPreference, defStyleAttr, defStyleRes); 68 69 setSummaryOn(TypedArrayUtils.getString(a, R.styleable.CheckBoxPreference_summaryOn, 70 R.styleable.CheckBoxPreference_android_summaryOn)); 71 72 setSummaryOff(TypedArrayUtils.getString(a, R.styleable.CheckBoxPreference_summaryOff, 73 R.styleable.CheckBoxPreference_android_summaryOff)); 74 75 setDisableDependentsState(TypedArrayUtils.getBoolean(a, 76 R.styleable.CheckBoxPreference_disableDependentsState, 77 R.styleable.CheckBoxPreference_android_disableDependentsState, false)); 78 79 a.recycle(); 80 } 81 82 public CheckBoxPreference(Context context, AttributeSet attrs) { 83 this(context, attrs, TypedArrayUtils.getAttr(context, R.attr.checkBoxPreferenceStyle, 84 android.R.attr.checkBoxPreferenceStyle)); 85 } 86 87 public CheckBoxPreference(Context context) { 88 this(context, null); 89 } 90 91 @Override 92 public void onBindViewHolder(PreferenceViewHolder holder) { 93 super.onBindViewHolder(holder); 94 95 syncCheckboxView(holder.findViewById(android.R.id.checkbox)); 96 97 syncSummaryView(holder); 98 } 99 100 /** 101 * @hide 102 */ 103 @RestrictTo(LIBRARY_GROUP) 104 @Override 105 protected void performClick(View view) { 106 super.performClick(view); 107 syncViewIfAccessibilityEnabled(view); 108 } 109 110 private void syncViewIfAccessibilityEnabled(View view) { 111 AccessibilityManager accessibilityManager = (AccessibilityManager) 112 getContext().getSystemService(Context.ACCESSIBILITY_SERVICE); 113 if (!accessibilityManager.isEnabled()) { 114 return; 115 } 116 117 View checkboxView = view.findViewById(android.R.id.checkbox); 118 syncCheckboxView(checkboxView); 119 120 View summaryView = view.findViewById(android.R.id.summary); 121 syncSummaryView(summaryView); 122 } 123 124 private void syncCheckboxView(View view) { 125 if (view instanceof CompoundButton) { 126 ((CompoundButton) view).setOnCheckedChangeListener(null); 127 } 128 if (view instanceof Checkable) { 129 ((Checkable) view).setChecked(mChecked); 130 } 131 if (view instanceof CompoundButton) { 132 ((CompoundButton) view).setOnCheckedChangeListener(mListener); 133 } 134 } 135 } 136