Home | History | Annotate | Download | only in deletionhelper
      1 /*
      2  * Copyright (C) 2016 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 com.android.storagemanager.deletionhelper;
     18 
     19 import android.content.Context;
     20 import android.os.Parcel;
     21 import android.os.Parcelable;
     22 import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
     23 import android.support.v7.preference.Preference;
     24 import android.support.v7.preference.PreferenceGroup;
     25 import android.support.v7.preference.PreferenceViewHolder;
     26 import android.util.AttributeSet;
     27 
     28 import android.view.View;
     29 import android.view.ViewGroup;
     30 import android.widget.Checkable;
     31 import android.widget.ImageView;
     32 
     33 import com.android.storagemanager.R;
     34 
     35 /**
     36  * CollapsibleCheckboxPreferenceGroup is a preference group that can be expanded or collapsed and
     37  * also has a checkbox.
     38  */
     39 public class CollapsibleCheckboxPreferenceGroup extends PreferenceGroup implements
     40         View.OnClickListener {
     41     private boolean mCollapsed;
     42     private boolean mChecked;
     43 
     44     public CollapsibleCheckboxPreferenceGroup(Context context) {
     45         this(context, null);
     46     }
     47 
     48     public CollapsibleCheckboxPreferenceGroup(Context context, AttributeSet attrs) {
     49         super(context, attrs);
     50         setLayoutResource(R.layout.deletion_preference);
     51         setWidgetLayoutResource(R.layout.preference_widget_checkbox);
     52     }
     53 
     54     @Override
     55     public void onBindViewHolder(PreferenceViewHolder holder) {
     56         super.onBindViewHolder(holder);
     57         View checkbox = holder.findViewById(com.android.internal.R.id.checkbox);
     58         if (checkbox != null && checkbox instanceof Checkable) {
     59             ((Checkable) checkbox).setChecked(mChecked);
     60 
     61             // Expand the touch target by making the parent the touch target.
     62             View parent = (View) checkbox.getParent();
     63             parent.setClickable(true);
     64             parent.setFocusable(true);
     65             parent.setOnClickListener(this);
     66         }
     67 
     68         // CollapsibleCheckboxPreferenceGroup considers expansion to be its "longer-term
     69         // (activation) state."
     70         final ImageView imageView = (ImageView) holder.findViewById(android.R.id.icon);
     71         imageView.setActivated(!mCollapsed);
     72     }
     73 
     74     @Override
     75     public boolean addPreference(Preference p) {
     76         super.addPreference(p);
     77         p.setVisible(!isCollapsed());
     78         return true;
     79     }
     80 
     81     // The preference click handler.
     82     @Override
     83     protected void onClick() {
     84         super.onClick();
     85         setCollapse(!isCollapsed());
     86     }
     87 
     88     // The checkbox view click handler.
     89     @Override
     90     public void onClick(View v) {
     91         super.onClick();
     92         setChecked(!isChecked());
     93 
     94         // We need to find the CheckBox in the parent view that we are using as a touch target.
     95         // If we don't update it before onClick finishes, the accessibility gives invalid
     96         // responses.
     97         ViewGroup parent = (ViewGroup) v;
     98         View child =  parent.findViewById(com.android.internal.R.id.checkbox);
     99         Checkable checkable = (Checkable) child;
    100         checkable.setChecked(mChecked);
    101     }
    102 
    103     /**
    104      * Return if the view is collapsed.
    105      */
    106     public boolean isCollapsed() {
    107         return mCollapsed;
    108     }
    109 
    110     /**
    111      * Returns the checked state of the preference.
    112      */
    113     public boolean isChecked() {
    114         return mChecked;
    115     }
    116 
    117     /**
    118      * Sets the checked state and notifies listeners of the state change.
    119      */
    120     public void setChecked(boolean checked) {
    121         if (mChecked != checked) {
    122             mChecked = checked;
    123 
    124             callChangeListener(checked);
    125             notifyDependencyChange(shouldDisableDependents());
    126             notifyChanged();
    127         }
    128     }
    129 
    130     @Override
    131     public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfoCompat info) {
    132         super.onInitializeAccessibilityNodeInfo(info);
    133         info.setCheckable(true);
    134         info.setChecked(isChecked());
    135     }
    136 
    137     @Override
    138     protected Parcelable onSaveInstanceState() {
    139         final Parcelable superState = super.onSaveInstanceState();
    140 
    141         final SavedState myState = new SavedState(superState);
    142         myState.checked = isChecked();
    143         myState.collapsed = isCollapsed();
    144         return myState;
    145     }
    146 
    147     @Override
    148     protected void onRestoreInstanceState(Parcelable state) {
    149         // Only restore the state if it is valid and our saved state.
    150         if (state == null || !SavedState.class.equals(state.getClass())) {
    151             super.onRestoreInstanceState(state);
    152             return;
    153         }
    154 
    155         SavedState myState = (SavedState) state;
    156         super.onRestoreInstanceState(myState.getSuperState());
    157         setChecked(myState.checked);
    158         setCollapse(myState.collapsed);
    159     }
    160 
    161     private void setCollapse(boolean isCollapsed) {
    162         if (mCollapsed == isCollapsed) {
    163             return;
    164         }
    165 
    166         mCollapsed = isCollapsed;
    167         setAllPreferencesVisibility(!isCollapsed);
    168         notifyChanged();
    169     }
    170 
    171     private void setAllPreferencesVisibility(boolean visible) {
    172         for (int i = 0; i < getPreferenceCount(); i++) {
    173             Preference p = getPreference(i);
    174             p.setVisible(visible);
    175         }
    176     }
    177 
    178     private static class SavedState extends BaseSavedState {
    179         boolean checked;
    180         boolean collapsed;
    181 
    182         public SavedState(Parcel source) {
    183             super(source);
    184             checked = source.readInt() != 0;
    185             collapsed = source.readInt() != 0;
    186         }
    187 
    188         public SavedState(Parcelable superState) {
    189             super(superState);
    190         }
    191 
    192         @Override
    193         public void writeToParcel(Parcel dest, int flags) {
    194             super.writeToParcel(dest, flags);
    195             dest.writeInt(checked ? 1 : 0);
    196             dest.writeInt(collapsed ? 1 : 0);
    197         }
    198 
    199         public static final Parcelable.Creator<SavedState> CREATOR =
    200                 new Parcelable.Creator<SavedState>() {
    201                     public SavedState createFromParcel(Parcel in) {
    202                         return new SavedState(in);
    203                     }
    204 
    205                     public SavedState[] newArray(int size) {
    206                         return new SavedState[size];
    207                     }
    208                 };
    209     }
    210 }
    211