SwitchBar.java revision b18e2423667b132d8de428fdbdb32572a1befe62
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 17package com.android.settings.widget; 18 19import android.content.Context; 20import android.content.res.TypedArray; 21import android.os.Parcel; 22import android.os.Parcelable; 23import android.util.AttributeSet; 24import android.util.TypedValue; 25import android.view.LayoutInflater; 26import android.view.View; 27import android.view.ViewGroup; 28import android.widget.CompoundButton; 29import android.widget.LinearLayout; 30 31import android.widget.Switch; 32import android.widget.TextView; 33import com.android.settings.R; 34 35import java.util.ArrayList; 36 37public 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