2 * Copyright (C) 2014 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com.android.settings.widget;
19 import android.content.Context;
20 import android.content.res.TypedArray;
21 import android.os.Parcel;
22 import android.os.Parcelable;
23 import android.text.SpannableStringBuilder;
24 import android.text.TextUtils;
25 import android.text.style.TextAppearanceSpan;
26 import android.util.AttributeSet;
27 import android.view.LayoutInflater;
28 import android.view.View;
29 import android.view.ViewGroup;
30 import android.widget.CompoundButton;
31 import android.widget.LinearLayout;
32 import android.widget.Switch;
33 import android.widget.TextView;
35 import com.android.settings.R;
37 import java.util.ArrayList;
39 public class SwitchBar extends LinearLayout implements CompoundButton.OnCheckedChangeListener,
40 View.OnClickListener {
42 public static interface OnSwitchChangeListener {
44 * Called when the checked state of the Switch has changed.
46 * @param switchView The Switch view whose state has changed.
47 * @param isChecked The new checked state of switchView.
49 void onSwitchChanged(Switch switchView, boolean isChecked);
52 private final TextAppearanceSpan mSummarySpan;
54 private ToggleSwitch mSwitch;
55 private TextView mTextView;
56 private String mLabel;
57 private String mSummary;
59 private int mStateOnLabel = R.string.switch_on_text;
60 private int mStateOffLabel = R.string.switch_off_text;
62 private ArrayList<OnSwitchChangeListener> mSwitchChangeListeners =
63 new ArrayList<OnSwitchChangeListener>();
65 private static int[] MARGIN_ATTRIBUTES = {
66 R.attr.switchBarMarginStart, R.attr.switchBarMarginEnd};
68 public SwitchBar(Context context) {
72 public SwitchBar(Context context, AttributeSet attrs) {
73 this(context, attrs, 0);
76 public SwitchBar(Context context, AttributeSet attrs, int defStyleAttr) {
77 this(context, attrs, defStyleAttr, 0);
80 public SwitchBar(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
81 super(context, attrs, defStyleAttr, defStyleRes);
83 LayoutInflater.from(context).inflate(R.layout.switch_bar, this);
85 final TypedArray a = context.obtainStyledAttributes(attrs, MARGIN_ATTRIBUTES);
86 int switchBarMarginStart = (int) a.getDimension(0, 0);
87 int switchBarMarginEnd = (int) a.getDimension(1, 0);
90 mTextView = (TextView) findViewById(R.id.switch_text);
91 mLabel = getResources().getString(R.string.switch_off_text);
92 mSummarySpan = new TextAppearanceSpan(mContext, R.style.TextAppearance_Small_SwitchBar);
94 ViewGroup.MarginLayoutParams lp = (MarginLayoutParams) mTextView.getLayoutParams();
95 lp.setMarginStart(switchBarMarginStart);
97 mSwitch = (ToggleSwitch) findViewById(R.id.switch_widget);
98 // Prevent onSaveInstanceState() to be called as we are managing the state of the Switch
100 mSwitch.setSaveEnabled(false);
101 lp = (MarginLayoutParams) mSwitch.getLayoutParams();
102 lp.setMarginEnd(switchBarMarginEnd);
104 addOnSwitchChangeListener(new OnSwitchChangeListener() {
106 public void onSwitchChanged(Switch switchView, boolean isChecked) {
107 setTextViewLabel(isChecked);
111 setOnClickListener(this);
114 setVisibility(View.GONE);
117 public void setOnStateOnLabel(int stringRes) {
118 mStateOnLabel = stringRes;
121 public void setOnStateOffLabel(int stringRes) {
122 mStateOffLabel = stringRes;
125 public void setTextViewLabel(boolean isChecked) {
126 mLabel = getResources()
127 .getString(isChecked ? R.string.switch_on_text : R.string.switch_off_text);
131 public void setSummary(String summary) {
136 private void updateText() {
137 if (TextUtils.isEmpty(mSummary)) {
138 mTextView.setText(mLabel);
141 final SpannableStringBuilder ssb = new SpannableStringBuilder(mLabel).append('\n');
142 final int start = ssb.length();
143 ssb.append(mSummary);
144 ssb.setSpan(mSummarySpan, start, ssb.length(), 0);
145 mTextView.setText(ssb);
148 public void setChecked(boolean checked) {
149 setTextViewLabel(checked);
150 mSwitch.setChecked(checked);
153 public void setCheckedInternal(boolean checked) {
154 setTextViewLabel(checked);
155 mSwitch.setCheckedInternal(checked);
158 public boolean isChecked() {
159 return mSwitch.isChecked();
162 public void setEnabled(boolean enabled) {
163 super.setEnabled(enabled);
164 mTextView.setEnabled(enabled);
165 mSwitch.setEnabled(enabled);
168 public final ToggleSwitch getSwitch() {
174 setVisibility(View.VISIBLE);
175 mSwitch.setOnCheckedChangeListener(this);
181 setVisibility(View.GONE);
182 mSwitch.setOnCheckedChangeListener(null);
186 public boolean isShowing() {
187 return (getVisibility() == View.VISIBLE);
191 public void onClick(View v) {
192 final boolean isChecked = !mSwitch.isChecked();
193 setChecked(isChecked);
196 public void propagateChecked(boolean isChecked) {
197 final int count = mSwitchChangeListeners.size();
198 for (int n = 0; n < count; n++) {
199 mSwitchChangeListeners.get(n).onSwitchChanged(mSwitch, isChecked);
204 public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
205 propagateChecked(isChecked);
208 public void addOnSwitchChangeListener(OnSwitchChangeListener listener) {
209 if (mSwitchChangeListeners.contains(listener)) {
210 throw new IllegalStateException("Cannot add twice the same OnSwitchChangeListener");
212 mSwitchChangeListeners.add(listener);
215 public void removeOnSwitchChangeListener(OnSwitchChangeListener listener) {
216 if (!mSwitchChangeListeners.contains(listener)) {
217 throw new IllegalStateException("Cannot remove OnSwitchChangeListener");
219 mSwitchChangeListeners.remove(listener);
222 static class SavedState extends BaseSavedState {
228 SavedState(Parcelable superState) {
233 * Constructor called from {@link #CREATOR}
235 private SavedState(Parcel in) {
237 checked = (Boolean)in.readValue(null);
238 visible = (Boolean)in.readValue(null);
239 resOnLabel = in.readInt();
240 resOffLabel = in.readInt();
244 public void writeToParcel(Parcel out, int flags) {
245 super.writeToParcel(out, flags);
246 out.writeValue(checked);
247 out.writeValue(visible);
248 out.writeInt(resOnLabel);
249 out.writeInt(resOffLabel);
253 public String toString() {
254 return "SwitchBar.SavedState{"
255 + Integer.toHexString(System.identityHashCode(this))
256 + " checked=" + checked
257 + " visible=" + visible
258 + " resOnLabel = " + resOnLabel
259 + " resOffLabel = " + resOffLabel
263 public static final Parcelable.Creator<SavedState> CREATOR
264 = new Parcelable.Creator<SavedState>() {
265 public SavedState createFromParcel(Parcel in) {
266 return new SavedState(in);
269 public SavedState[] newArray(int size) {
270 return new SavedState[size];
276 public Parcelable onSaveInstanceState() {
277 Parcelable superState = super.onSaveInstanceState();
279 SavedState ss = new SavedState(superState);
280 ss.checked = mSwitch.isChecked();
281 ss.visible = isShowing();
282 ss.resOnLabel = mStateOnLabel;
283 ss.resOffLabel = mStateOffLabel;
288 public void onRestoreInstanceState(Parcelable state) {
289 SavedState ss = (SavedState) state;
291 super.onRestoreInstanceState(ss.getSuperState());
293 mSwitch.setCheckedInternal(ss.checked);
294 setOnStateOnLabel(ss.resOnLabel);
295 setOnStateOffLabel(ss.resOffLabel);
296 setTextViewLabel(ss.checked);
297 setVisibility(ss.visible ? View.VISIBLE : View.GONE);
298 mSwitch.setOnCheckedChangeListener(ss.visible ? this : null);