Home | History | Annotate | Download | only in widget
      1 /*
      2  * Copyright (C) 2014 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.settings.widget;
     18 
     19 import android.content.Context;
     20 import android.content.res.TypedArray;
     21 import android.os.Parcel;
     22 import android.os.Parcelable;
     23 import android.util.AttributeSet;
     24 import android.util.TypedValue;
     25 import android.view.LayoutInflater;
     26 import android.view.View;
     27 import android.view.ViewGroup;
     28 import android.widget.CompoundButton;
     29 import android.widget.LinearLayout;
     30 
     31 import android.widget.Switch;
     32 import android.widget.TextView;
     33 import com.android.settings.R;
     34 
     35 import java.util.ArrayList;
     36 
     37 public class SwitchBar extends LinearLayout implements CompoundButton.OnCheckedChangeListener,
     38         View.OnClickListener {
     39 
     40     public static interface OnSwitchChangeListener {
     41         /**
     42          * Called when the checked state of the Switch has changed.
     43          *
     44          * @param switchView The Switch view whose state has changed.
     45          * @param isChecked  The new checked state of switchView.
     46          */
     47         void onSwitchChanged(Switch switchView, boolean isChecked);
     48     }
     49 
     50     private ToggleSwitch mSwitch;
     51     private TextView mTextView;
     52 
     53     private ArrayList<OnSwitchChangeListener> mSwitchChangeListeners =
     54             new ArrayList<OnSwitchChangeListener>();
     55 
     56     private static int[] MARGIN_ATTRIBUTES = {
     57             R.attr.switchBarMarginStart, R.attr.switchBarMarginEnd};
     58 
     59     public SwitchBar(Context context) {
     60         this(context, null);
     61     }
     62 
     63     public SwitchBar(Context context, AttributeSet attrs) {
     64         this(context, attrs, 0);
     65     }
     66 
     67     public SwitchBar(Context context, AttributeSet attrs, int defStyleAttr) {
     68         this(context, attrs, defStyleAttr, 0);
     69     }
     70 
     71     public SwitchBar(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
     72         super(context, attrs, defStyleAttr, defStyleRes);
     73 
     74         LayoutInflater.from(context).inflate(R.layout.switch_bar, this);
     75 
     76         final TypedArray a = context.obtainStyledAttributes(attrs, MARGIN_ATTRIBUTES);
     77         int switchBarMarginStart = (int) a.getDimension(0, 0);
     78         int switchBarMarginEnd = (int) a.getDimension(1, 0);
     79         a.recycle();
     80 
     81         mTextView = (TextView) findViewById(R.id.switch_text);
     82         mTextView.setText(R.string.switch_off_text);
     83         ViewGroup.MarginLayoutParams lp = (MarginLayoutParams) mTextView.getLayoutParams();
     84         lp.setMarginStart(switchBarMarginStart);
     85 
     86         mSwitch = (ToggleSwitch) findViewById(R.id.switch_widget);
     87         // Prevent onSaveInstanceState() to be called as we are managing the state of the Switch
     88         // on our own
     89         mSwitch.setSaveEnabled(false);
     90         lp = (MarginLayoutParams) mSwitch.getLayoutParams();
     91         lp.setMarginEnd(switchBarMarginEnd);
     92 
     93         addOnSwitchChangeListener(new OnSwitchChangeListener() {
     94             @Override
     95             public void onSwitchChanged(Switch switchView, boolean isChecked) {
     96                 setTextViewLabel(isChecked);
     97             }
     98         });
     99 
    100         setOnClickListener(this);
    101 
    102         // Default is hide
    103         setVisibility(View.GONE);
    104     }
    105 
    106     public void setTextViewLabel(boolean isChecked) {
    107         mTextView.setText(isChecked ? R.string.switch_on_text : R.string.switch_off_text);
    108     }
    109 
    110     public void setChecked(boolean checked) {
    111         setTextViewLabel(checked);
    112         mSwitch.setChecked(checked);
    113     }
    114 
    115     public void setCheckedInternal(boolean checked) {
    116         setTextViewLabel(checked);
    117         mSwitch.setCheckedInternal(checked);
    118     }
    119 
    120     public boolean isChecked() {
    121         return mSwitch.isChecked();
    122     }
    123 
    124     public void setEnabled(boolean enabled) {
    125         super.setEnabled(enabled);
    126         mTextView.setEnabled(enabled);
    127         mSwitch.setEnabled(enabled);
    128     }
    129 
    130     public final ToggleSwitch getSwitch() {
    131         return mSwitch;
    132     }
    133 
    134     public void show() {
    135         if (!isShowing()) {
    136             setVisibility(View.VISIBLE);
    137             mSwitch.setOnCheckedChangeListener(this);
    138         }
    139     }
    140 
    141     public void hide() {
    142         if (isShowing()) {
    143             setVisibility(View.GONE);
    144             mSwitch.setOnCheckedChangeListener(null);
    145         }
    146     }
    147 
    148     public boolean isShowing() {
    149         return (getVisibility() == View.VISIBLE);
    150     }
    151 
    152     @Override
    153     public void onClick(View v) {
    154         final boolean isChecked = !mSwitch.isChecked();
    155         setChecked(isChecked);
    156     }
    157 
    158     public void propagateChecked(boolean isChecked) {
    159         final int count = mSwitchChangeListeners.size();
    160         for (int n = 0; n < count; n++) {
    161             mSwitchChangeListeners.get(n).onSwitchChanged(mSwitch, isChecked);
    162         }
    163     }
    164 
    165     @Override
    166     public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
    167         propagateChecked(isChecked);
    168     }
    169 
    170     public void addOnSwitchChangeListener(OnSwitchChangeListener listener) {
    171         if (mSwitchChangeListeners.contains(listener)) {
    172             throw new IllegalStateException("Cannot add twice the same OnSwitchChangeListener");
    173         }
    174         mSwitchChangeListeners.add(listener);
    175     }
    176 
    177     public void removeOnSwitchChangeListener(OnSwitchChangeListener listener) {
    178         if (!mSwitchChangeListeners.contains(listener)) {
    179             throw new IllegalStateException("Cannot remove OnSwitchChangeListener");
    180         }
    181         mSwitchChangeListeners.remove(listener);
    182     }
    183 
    184     static class SavedState extends BaseSavedState {
    185         boolean checked;
    186         boolean visible;
    187 
    188         SavedState(Parcelable superState) {
    189             super(superState);
    190         }
    191 
    192         /**
    193          * Constructor called from {@link #CREATOR}
    194          */
    195         private SavedState(Parcel in) {
    196             super(in);
    197             checked = (Boolean)in.readValue(null);
    198             visible = (Boolean)in.readValue(null);
    199         }
    200 
    201         @Override
    202         public void writeToParcel(Parcel out, int flags) {
    203             super.writeToParcel(out, flags);
    204             out.writeValue(checked);
    205             out.writeValue(visible);
    206         }
    207 
    208         @Override
    209         public String toString() {
    210             return "SwitchBar.SavedState{"
    211                     + Integer.toHexString(System.identityHashCode(this))
    212                     + " checked=" + checked
    213                     + " visible=" + visible + "}";
    214         }
    215 
    216         public static final Parcelable.Creator<SavedState> CREATOR
    217                 = new Parcelable.Creator<SavedState>() {
    218             public SavedState createFromParcel(Parcel in) {
    219                 return new SavedState(in);
    220             }
    221 
    222             public SavedState[] newArray(int size) {
    223                 return new SavedState[size];
    224             }
    225         };
    226     }
    227 
    228     @Override
    229     public Parcelable onSaveInstanceState() {
    230         Parcelable superState = super.onSaveInstanceState();
    231 
    232         SavedState ss = new SavedState(superState);
    233         ss.checked = mSwitch.isChecked();
    234         ss.visible = isShowing();
    235         return ss;
    236     }
    237 
    238     @Override
    239     public void onRestoreInstanceState(Parcelable state) {
    240         SavedState ss = (SavedState) state;
    241 
    242         super.onRestoreInstanceState(ss.getSuperState());
    243 
    244         mSwitch.setCheckedInternal(ss.checked);
    245         setTextViewLabel(ss.checked);
    246         setVisibility(ss.visible ? View.VISIBLE : View.GONE);
    247         mSwitch.setOnCheckedChangeListener(ss.visible ? this : null);
    248 
    249         requestLayout();
    250     }
    251 }
    252