OSDN Git Service

Merge tag 'android-6.0.1_r74' into HEAD
[android-x86/packages-apps-Settings.git] / src / com / android / settings / widget / SwitchBar.java
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.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;
34
35 import com.android.settings.R;
36
37 import java.util.ArrayList;
38
39 public class SwitchBar extends LinearLayout implements CompoundButton.OnCheckedChangeListener,
40         View.OnClickListener {
41
42     public static interface OnSwitchChangeListener {
43         /**
44          * Called when the checked state of the Switch has changed.
45          *
46          * @param switchView The Switch view whose state has changed.
47          * @param isChecked  The new checked state of switchView.
48          */
49         void onSwitchChanged(Switch switchView, boolean isChecked);
50     }
51
52     private final TextAppearanceSpan mSummarySpan;
53
54     private ToggleSwitch mSwitch;
55     private TextView mTextView;
56     private String mLabel;
57     private String mSummary;
58
59     private int mStateOnLabel = R.string.switch_on_text;
60     private int mStateOffLabel = R.string.switch_off_text;
61
62     private ArrayList<OnSwitchChangeListener> mSwitchChangeListeners =
63             new ArrayList<OnSwitchChangeListener>();
64
65     private static int[] MARGIN_ATTRIBUTES = {
66             R.attr.switchBarMarginStart, R.attr.switchBarMarginEnd};
67
68     public SwitchBar(Context context) {
69         this(context, null);
70     }
71
72     public SwitchBar(Context context, AttributeSet attrs) {
73         this(context, attrs, 0);
74     }
75
76     public SwitchBar(Context context, AttributeSet attrs, int defStyleAttr) {
77         this(context, attrs, defStyleAttr, 0);
78     }
79
80     public SwitchBar(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
81         super(context, attrs, defStyleAttr, defStyleRes);
82
83         LayoutInflater.from(context).inflate(R.layout.switch_bar, this);
84
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);
88         a.recycle();
89
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);
93         updateText();
94         ViewGroup.MarginLayoutParams lp = (MarginLayoutParams) mTextView.getLayoutParams();
95         lp.setMarginStart(switchBarMarginStart);
96
97         mSwitch = (ToggleSwitch) findViewById(R.id.switch_widget);
98         // Prevent onSaveInstanceState() to be called as we are managing the state of the Switch
99         // on our own
100         mSwitch.setSaveEnabled(false);
101         lp = (MarginLayoutParams) mSwitch.getLayoutParams();
102         lp.setMarginEnd(switchBarMarginEnd);
103
104         addOnSwitchChangeListener(new OnSwitchChangeListener() {
105             @Override
106             public void onSwitchChanged(Switch switchView, boolean isChecked) {
107                 setTextViewLabel(isChecked);
108             }
109         });
110
111         setOnClickListener(this);
112
113         // Default is hide
114         setVisibility(View.GONE);
115     }
116
117     public void setOnStateOnLabel(int stringRes) {
118         mStateOnLabel = stringRes;
119     }
120
121     public void setOnStateOffLabel(int stringRes) {
122         mStateOffLabel = stringRes;
123     }
124
125     public void setTextViewLabel(boolean isChecked) {
126         mLabel = getResources()
127                 .getString(isChecked ? R.string.switch_on_text : R.string.switch_off_text);
128         updateText();
129     }
130
131     public void setSummary(String summary) {
132         mSummary = summary;
133         updateText();
134     }
135
136     private void updateText() {
137         if (TextUtils.isEmpty(mSummary)) {
138             mTextView.setText(mLabel);
139             return;
140         }
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);
146     }
147
148     public void setChecked(boolean checked) {
149         setTextViewLabel(checked);
150         mSwitch.setChecked(checked);
151     }
152
153     public void setCheckedInternal(boolean checked) {
154         setTextViewLabel(checked);
155         mSwitch.setCheckedInternal(checked);
156     }
157
158     public boolean isChecked() {
159         return mSwitch.isChecked();
160     }
161
162     public void setEnabled(boolean enabled) {
163         super.setEnabled(enabled);
164         mTextView.setEnabled(enabled);
165         mSwitch.setEnabled(enabled);
166     }
167
168     public final ToggleSwitch getSwitch() {
169         return mSwitch;
170     }
171
172     public void show() {
173         if (!isShowing()) {
174             setVisibility(View.VISIBLE);
175             mSwitch.setOnCheckedChangeListener(this);
176         }
177     }
178
179     public void hide() {
180         if (isShowing()) {
181             setVisibility(View.GONE);
182             mSwitch.setOnCheckedChangeListener(null);
183         }
184     }
185
186     public boolean isShowing() {
187         return (getVisibility() == View.VISIBLE);
188     }
189
190     @Override
191     public void onClick(View v) {
192         final boolean isChecked = !mSwitch.isChecked();
193         setChecked(isChecked);
194     }
195
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);
200         }
201     }
202
203     @Override
204     public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
205         propagateChecked(isChecked);
206     }
207
208     public void addOnSwitchChangeListener(OnSwitchChangeListener listener) {
209         if (mSwitchChangeListeners.contains(listener)) {
210             throw new IllegalStateException("Cannot add twice the same OnSwitchChangeListener");
211         }
212         mSwitchChangeListeners.add(listener);
213     }
214
215     public void removeOnSwitchChangeListener(OnSwitchChangeListener listener) {
216         if (!mSwitchChangeListeners.contains(listener)) {
217             throw new IllegalStateException("Cannot remove OnSwitchChangeListener");
218         }
219         mSwitchChangeListeners.remove(listener);
220     }
221
222     static class SavedState extends BaseSavedState {
223         boolean checked;
224         boolean visible;
225         int resOnLabel;
226         int resOffLabel;
227
228         SavedState(Parcelable superState) {
229             super(superState);
230         }
231
232         /**
233          * Constructor called from {@link #CREATOR}
234          */
235         private SavedState(Parcel in) {
236             super(in);
237             checked = (Boolean)in.readValue(null);
238             visible = (Boolean)in.readValue(null);
239             resOnLabel = in.readInt();
240             resOffLabel = in.readInt();
241         }
242
243         @Override
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);
250         }
251
252         @Override
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
260                     + "}";
261         }
262
263         public static final Parcelable.Creator<SavedState> CREATOR
264                 = new Parcelable.Creator<SavedState>() {
265             public SavedState createFromParcel(Parcel in) {
266                 return new SavedState(in);
267             }
268
269             public SavedState[] newArray(int size) {
270                 return new SavedState[size];
271             }
272         };
273     }
274
275     @Override
276     public Parcelable onSaveInstanceState() {
277         Parcelable superState = super.onSaveInstanceState();
278
279         SavedState ss = new SavedState(superState);
280         ss.checked = mSwitch.isChecked();
281         ss.visible = isShowing();
282         ss.resOnLabel = mStateOnLabel;
283         ss.resOffLabel = mStateOffLabel;
284         return ss;
285     }
286
287     @Override
288     public void onRestoreInstanceState(Parcelable state) {
289         SavedState ss = (SavedState) state;
290
291         super.onRestoreInstanceState(ss.getSuperState());
292
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);
299
300         requestLayout();
301     }
302 }