blob: 092e31c5a6b4897ac13da3e47284f11b55460feb [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2007 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 android.widget;
18
Alan Viverette91174362014-06-17 14:51:45 -070019import android.annotation.Nullable;
20import android.graphics.PorterDuff;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080021import com.android.internal.R;
22
23import android.content.Context;
Alan Viverette91174362014-06-17 14:51:45 -070024import android.content.res.ColorStateList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080025import android.content.res.TypedArray;
26import android.graphics.Canvas;
27import android.graphics.drawable.Drawable;
28import android.os.Parcel;
29import android.os.Parcelable;
30import android.util.AttributeSet;
31import android.view.Gravity;
Alan Viveretted4e77902014-10-27 17:50:51 -070032import android.view.SoundEffectConstants;
Steve Zeigler7a367882010-02-23 16:39:08 -080033import android.view.ViewDebug;
Jean-Baptiste Querucf4550c2009-07-21 11:16:54 -070034import android.view.accessibility.AccessibilityEvent;
Svetoslav Ganov13774d22011-06-15 15:29:51 -070035import android.view.accessibility.AccessibilityNodeInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080036
37/**
38 * <p>
39 * A button with two states, checked and unchecked. When the button is pressed
40 * or clicked, the state changes automatically.
41 * </p>
42 *
43 * <p><strong>XML attributes</strong></p>
44 * <p>
45 * See {@link android.R.styleable#CompoundButton
46 * CompoundButton Attributes}, {@link android.R.styleable#Button Button
47 * Attributes}, {@link android.R.styleable#TextView TextView Attributes}, {@link
48 * android.R.styleable#View View Attributes}
49 * </p>
50 */
51public abstract class CompoundButton extends Button implements Checkable {
52 private boolean mChecked;
53 private int mButtonResource;
54 private boolean mBroadcasting;
Alan Viverette91174362014-06-17 14:51:45 -070055
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080056 private Drawable mButtonDrawable;
Alan Viverettea4264452014-07-28 16:02:55 -070057 private ColorStateList mButtonTintList = null;
Alan Viveretteb56f5d22014-09-14 15:48:50 -070058 private PorterDuff.Mode mButtonTintMode = null;
Alan Viverette91174362014-06-17 14:51:45 -070059 private boolean mHasButtonTint = false;
Alan Viveretteb56f5d22014-09-14 15:48:50 -070060 private boolean mHasButtonTintMode = false;
Alan Viverette91174362014-06-17 14:51:45 -070061
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080062 private OnCheckedChangeListener mOnCheckedChangeListener;
63 private OnCheckedChangeListener mOnCheckedChangeWidgetListener;
64
65 private static final int[] CHECKED_STATE_SET = {
66 R.attr.state_checked
67 };
68
69 public CompoundButton(Context context) {
70 this(context, null);
71 }
72
73 public CompoundButton(Context context, AttributeSet attrs) {
74 this(context, attrs, 0);
75 }
76
Alan Viverette617feb92013-09-09 18:09:13 -070077 public CompoundButton(Context context, AttributeSet attrs, int defStyleAttr) {
78 this(context, attrs, defStyleAttr, 0);
79 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080080
Alan Viverette617feb92013-09-09 18:09:13 -070081 public CompoundButton(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
82 super(context, attrs, defStyleAttr, defStyleRes);
83
84 final TypedArray a = context.obtainStyledAttributes(
85 attrs, com.android.internal.R.styleable.CompoundButton, defStyleAttr, defStyleRes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080086
Alan Viverette91174362014-06-17 14:51:45 -070087 final Drawable d = a.getDrawable(com.android.internal.R.styleable.CompoundButton_button);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080088 if (d != null) {
89 setButtonDrawable(d);
90 }
91
Alan Viveretteb56f5d22014-09-14 15:48:50 -070092 if (a.hasValue(R.styleable.CompoundButton_buttonTintMode)) {
93 mButtonTintMode = Drawable.parseTintMode(a.getInt(
94 R.styleable.CompoundButton_buttonTintMode, -1), mButtonTintMode);
95 mHasButtonTintMode = true;
96 }
Alan Viverette4f64c042014-07-21 17:49:13 -070097
Alan Viverette91174362014-06-17 14:51:45 -070098 if (a.hasValue(R.styleable.CompoundButton_buttonTint)) {
Alan Viverettea4264452014-07-28 16:02:55 -070099 mButtonTintList = a.getColorStateList(R.styleable.CompoundButton_buttonTint);
Alan Viverette91174362014-06-17 14:51:45 -0700100 mHasButtonTint = true;
Alan Viverette91174362014-06-17 14:51:45 -0700101 }
102
103 final boolean checked = a.getBoolean(
104 com.android.internal.R.styleable.CompoundButton_checked, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800105 setChecked(checked);
106
107 a.recycle();
Alan Viveretteb56f5d22014-09-14 15:48:50 -0700108
109 applyButtonTint();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800110 }
111
112 public void toggle() {
113 setChecked(!mChecked);
114 }
115
116 @Override
117 public boolean performClick() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800118 toggle();
Alan Viveretted4e77902014-10-27 17:50:51 -0700119
120 final boolean handled = super.performClick();
121 if (!handled) {
122 // View only makes a sound effect if the onClickListener was
123 // called, so we'll need to make one here instead.
124 playSoundEffect(SoundEffectConstants.CLICK);
125 }
126
127 return handled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800128 }
129
Steve Zeigler7a367882010-02-23 16:39:08 -0800130 @ViewDebug.ExportedProperty
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800131 public boolean isChecked() {
132 return mChecked;
133 }
134
135 /**
136 * <p>Changes the checked state of this button.</p>
137 *
138 * @param checked true to check the button, false to uncheck it
139 */
140 public void setChecked(boolean checked) {
141 if (mChecked != checked) {
142 mChecked = checked;
143 refreshDrawableState();
Alan Viverette77e9a282013-09-12 17:16:09 -0700144 notifyViewAccessibilityStateChangedIfNeeded(
145 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800146
147 // Avoid infinite recursions if setChecked() is called from a listener
148 if (mBroadcasting) {
149 return;
150 }
151
152 mBroadcasting = true;
153 if (mOnCheckedChangeListener != null) {
154 mOnCheckedChangeListener.onCheckedChanged(this, mChecked);
155 }
156 if (mOnCheckedChangeWidgetListener != null) {
157 mOnCheckedChangeWidgetListener.onCheckedChanged(this, mChecked);
158 }
Jean-Baptiste Querucf4550c2009-07-21 11:16:54 -0700159
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800160 mBroadcasting = false;
161 }
162 }
163
164 /**
165 * Register a callback to be invoked when the checked state of this button
166 * changes.
167 *
168 * @param listener the callback to call on checked state change
169 */
170 public void setOnCheckedChangeListener(OnCheckedChangeListener listener) {
171 mOnCheckedChangeListener = listener;
172 }
173
174 /**
175 * Register a callback to be invoked when the checked state of this button
176 * changes. This callback is used for internal purpose only.
177 *
178 * @param listener the callback to call on checked state change
179 * @hide
180 */
181 void setOnCheckedChangeWidgetListener(OnCheckedChangeListener listener) {
182 mOnCheckedChangeWidgetListener = listener;
183 }
184
185 /**
186 * Interface definition for a callback to be invoked when the checked state
187 * of a compound button changed.
188 */
189 public static interface OnCheckedChangeListener {
190 /**
191 * Called when the checked state of a compound button has changed.
192 *
193 * @param buttonView The compound button view whose state has changed.
194 * @param isChecked The new checked state of buttonView.
195 */
196 void onCheckedChanged(CompoundButton buttonView, boolean isChecked);
197 }
198
199 /**
Alan Viverette91174362014-06-17 14:51:45 -0700200 * Set the button graphic to a given Drawable, identified by its resource
201 * id.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800202 *
Alan Viverette91174362014-06-17 14:51:45 -0700203 * @param resid the resource id of the drawable to use as the button
204 * graphic
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800205 */
206 public void setButtonDrawable(int resid) {
207 if (resid != 0 && resid == mButtonResource) {
208 return;
209 }
210
211 mButtonResource = resid;
212
213 Drawable d = null;
214 if (mButtonResource != 0) {
Alan Viverette8eea3ea2014-02-03 18:40:20 -0800215 d = getContext().getDrawable(mButtonResource);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800216 }
217 setButtonDrawable(d);
218 }
219
220 /**
Alan Viverette91174362014-06-17 14:51:45 -0700221 * Set the button graphic to a given Drawable
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800222 *
Alan Viverette91174362014-06-17 14:51:45 -0700223 * @param d The Drawable to use as the button graphic
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800224 */
225 public void setButtonDrawable(Drawable d) {
Alan Viverette91174362014-06-17 14:51:45 -0700226 if (mButtonDrawable != d) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800227 if (mButtonDrawable != null) {
228 mButtonDrawable.setCallback(null);
229 unscheduleDrawable(mButtonDrawable);
230 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800231
Alan Viverette91174362014-06-17 14:51:45 -0700232 mButtonDrawable = d;
233
234 if (d != null) {
235 d.setCallback(this);
236 d.setLayoutDirection(getLayoutDirection());
237 if (d.isStateful()) {
238 d.setState(getDrawableState());
239 }
240 d.setVisible(getVisibility() == VISIBLE, false);
241 setMinHeight(d.getIntrinsicHeight());
242 applyButtonTint();
243 }
244 }
245 }
246
247 /**
Alan Viverette91174362014-06-17 14:51:45 -0700248 * Applies a tint to the button drawable. Does not modify the current tint
Alan Viveretteb56f5d22014-09-14 15:48:50 -0700249 * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
Alan Viverette91174362014-06-17 14:51:45 -0700250 * <p>
251 * Subsequent calls to {@link #setButtonDrawable(Drawable)} will
252 * automatically mutate the drawable and apply the specified tint and tint
253 * mode using
Alan Viverettea4264452014-07-28 16:02:55 -0700254 * {@link Drawable#setTintList(ColorStateList)}.
Alan Viverette91174362014-06-17 14:51:45 -0700255 *
256 * @param tint the tint to apply, may be {@code null} to clear tint
257 *
258 * @attr ref android.R.styleable#CompoundButton_buttonTint
Alan Viverettea4264452014-07-28 16:02:55 -0700259 * @see #setButtonTintList(ColorStateList)
260 * @see Drawable#setTintList(ColorStateList)
Alan Viverette91174362014-06-17 14:51:45 -0700261 */
Alan Viverettea4264452014-07-28 16:02:55 -0700262 public void setButtonTintList(@Nullable ColorStateList tint) {
263 mButtonTintList = tint;
Alan Viverette4f64c042014-07-21 17:49:13 -0700264 mHasButtonTint = true;
265
266 applyButtonTint();
Alan Viverette91174362014-06-17 14:51:45 -0700267 }
268
269 /**
270 * @return the tint applied to the button drawable
271 * @attr ref android.R.styleable#CompoundButton_buttonTint
Alan Viverettea4264452014-07-28 16:02:55 -0700272 * @see #setButtonTintList(ColorStateList)
Alan Viverette91174362014-06-17 14:51:45 -0700273 */
274 @Nullable
Alan Viverettea4264452014-07-28 16:02:55 -0700275 public ColorStateList getButtonTintList() {
276 return mButtonTintList;
Alan Viverette91174362014-06-17 14:51:45 -0700277 }
278
279 /**
280 * Specifies the blending mode used to apply the tint specified by
Alan Viverettea4264452014-07-28 16:02:55 -0700281 * {@link #setButtonTintList(ColorStateList)}} to the button drawable. The
Alan Viveretteb56f5d22014-09-14 15:48:50 -0700282 * default mode is {@link PorterDuff.Mode#SRC_IN}.
Alan Viverette91174362014-06-17 14:51:45 -0700283 *
284 * @param tintMode the blending mode used to apply the tint, may be
285 * {@code null} to clear tint
286 * @attr ref android.R.styleable#CompoundButton_buttonTintMode
Alan Viverette4f64c042014-07-21 17:49:13 -0700287 * @see #getButtonTintMode()
Alan Viverettea4264452014-07-28 16:02:55 -0700288 * @see Drawable#setTintMode(PorterDuff.Mode)
Alan Viverette91174362014-06-17 14:51:45 -0700289 */
290 public void setButtonTintMode(@Nullable PorterDuff.Mode tintMode) {
Alan Viverette4f64c042014-07-21 17:49:13 -0700291 mButtonTintMode = tintMode;
Alan Viveretteb56f5d22014-09-14 15:48:50 -0700292 mHasButtonTintMode = true;
Alan Viverette4f64c042014-07-21 17:49:13 -0700293
294 applyButtonTint();
Alan Viverette91174362014-06-17 14:51:45 -0700295 }
296
297 /**
298 * @return the blending mode used to apply the tint to the button drawable
299 * @attr ref android.R.styleable#CompoundButton_buttonTintMode
Alan Viverette4f64c042014-07-21 17:49:13 -0700300 * @see #setButtonTintMode(PorterDuff.Mode)
Alan Viverette91174362014-06-17 14:51:45 -0700301 */
302 @Nullable
303 public PorterDuff.Mode getButtonTintMode() {
304 return mButtonTintMode;
305 }
306
307 private void applyButtonTint() {
Alan Viveretteb56f5d22014-09-14 15:48:50 -0700308 if (mButtonDrawable != null && (mHasButtonTint || mHasButtonTintMode)) {
Alan Viverette91174362014-06-17 14:51:45 -0700309 mButtonDrawable = mButtonDrawable.mutate();
Alan Viveretteb56f5d22014-09-14 15:48:50 -0700310
311 if (mHasButtonTint) {
312 mButtonDrawable.setTintList(mButtonTintList);
313 }
314
315 if (mHasButtonTintMode) {
316 mButtonDrawable.setTintMode(mButtonTintMode);
317 }
Alan Viverette91174362014-06-17 14:51:45 -0700318 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800319 }
320
321 @Override
Svetoslav Ganov30401322011-05-12 18:53:45 -0700322 public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
323 super.onInitializeAccessibilityEvent(event);
Svetoslav Ganov8a78fd42012-01-17 14:36:46 -0800324 event.setClassName(CompoundButton.class.getName());
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700325 event.setChecked(mChecked);
Jean-Baptiste Querucf4550c2009-07-21 11:16:54 -0700326 }
327
328 @Override
Svetoslav Ganov13774d22011-06-15 15:29:51 -0700329 public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
330 super.onInitializeAccessibilityNodeInfo(info);
Svetoslav Ganov8a78fd42012-01-17 14:36:46 -0800331 info.setClassName(CompoundButton.class.getName());
Svetoslav Ganov0f55cc32011-07-17 10:51:49 -0700332 info.setCheckable(true);
Svetoslav Ganov13774d22011-06-15 15:29:51 -0700333 info.setChecked(mChecked);
334 }
335
336 @Override
Fabrice Di Meglio28426792012-06-05 16:41:18 -0700337 public int getCompoundPaddingLeft() {
338 int padding = super.getCompoundPaddingLeft();
339 if (!isLayoutRtl()) {
340 final Drawable buttonDrawable = mButtonDrawable;
341 if (buttonDrawable != null) {
342 padding += buttonDrawable.getIntrinsicWidth();
343 }
344 }
345 return padding;
346 }
347
348 @Override
349 public int getCompoundPaddingRight() {
350 int padding = super.getCompoundPaddingRight();
351 if (isLayoutRtl()) {
352 final Drawable buttonDrawable = mButtonDrawable;
353 if (buttonDrawable != null) {
354 padding += buttonDrawable.getIntrinsicWidth();
355 }
356 }
357 return padding;
358 }
359
Fabrice Di Megliob878ddb2012-11-27 17:44:33 -0800360 /**
361 * @hide
362 */
363 @Override
364 public int getHorizontalOffsetForDrawables() {
365 final Drawable buttonDrawable = mButtonDrawable;
366 return (buttonDrawable != null) ? buttonDrawable.getIntrinsicWidth() : 0;
367 }
368
Fabrice Di Meglio28426792012-06-05 16:41:18 -0700369 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800370 protected void onDraw(Canvas canvas) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800371 final Drawable buttonDrawable = mButtonDrawable;
372 if (buttonDrawable != null) {
373 final int verticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK;
Fabrice Di Meglio28426792012-06-05 16:41:18 -0700374 final int drawableHeight = buttonDrawable.getIntrinsicHeight();
375 final int drawableWidth = buttonDrawable.getIntrinsicWidth();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800376
Alan Viverette61956602014-04-22 19:07:06 -0700377 final int top;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800378 switch (verticalGravity) {
379 case Gravity.BOTTOM:
Fabrice Di Meglio28426792012-06-05 16:41:18 -0700380 top = getHeight() - drawableHeight;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800381 break;
382 case Gravity.CENTER_VERTICAL:
Fabrice Di Meglio28426792012-06-05 16:41:18 -0700383 top = (getHeight() - drawableHeight) / 2;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800384 break;
Alan Viverette61956602014-04-22 19:07:06 -0700385 default:
386 top = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800387 }
Alan Viverette61956602014-04-22 19:07:06 -0700388 final int bottom = top + drawableHeight;
389 final int left = isLayoutRtl() ? getWidth() - drawableWidth : 0;
390 final int right = isLayoutRtl() ? getWidth() : drawableWidth;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800391
Fabrice Di Meglio28426792012-06-05 16:41:18 -0700392 buttonDrawable.setBounds(left, top, right, bottom);
Alan Viverette61956602014-04-22 19:07:06 -0700393
394 final Drawable background = getBackground();
Alan Viverettec80ad992014-05-19 15:46:17 -0700395 if (background != null) {
Alan Viverette61956602014-04-22 19:07:06 -0700396 background.setHotspotBounds(left, top, right, bottom);
397 }
398 }
399
400 super.onDraw(canvas);
401
402 if (buttonDrawable != null) {
Alan Viveretteb95c3362014-10-17 17:19:12 -0700403 final int scrollX = mScrollX;
404 final int scrollY = mScrollY;
405 if (scrollX == 0 && scrollY == 0) {
406 buttonDrawable.draw(canvas);
407 } else {
408 canvas.translate(scrollX, scrollY);
409 buttonDrawable.draw(canvas);
410 canvas.translate(-scrollX, -scrollY);
411 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800412 }
413 }
414
415 @Override
416 protected int[] onCreateDrawableState(int extraSpace) {
417 final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
418 if (isChecked()) {
419 mergeDrawableStates(drawableState, CHECKED_STATE_SET);
420 }
421 return drawableState;
422 }
423
424 @Override
425 protected void drawableStateChanged() {
426 super.drawableStateChanged();
427
428 if (mButtonDrawable != null) {
429 int[] myDrawableState = getDrawableState();
430
431 // Set the state of the Drawable
432 mButtonDrawable.setState(myDrawableState);
433
434 invalidate();
435 }
436 }
437
Alan Viverettecebc6ba2014-06-13 15:52:13 -0700438 @Override
Alan Viverette8de14942014-06-18 18:05:15 -0700439 public void drawableHotspotChanged(float x, float y) {
440 super.drawableHotspotChanged(x, y);
Alan Viverettecebc6ba2014-06-13 15:52:13 -0700441
442 if (mButtonDrawable != null) {
443 mButtonDrawable.setHotspot(x, y);
444 }
445 }
446
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800447 @Override
448 protected boolean verifyDrawable(Drawable who) {
449 return super.verifyDrawable(who) || who == mButtonDrawable;
450 }
451
Dianne Hackborne2136772010-11-04 15:08:59 -0700452 @Override
453 public void jumpDrawablesToCurrentState() {
454 super.jumpDrawablesToCurrentState();
455 if (mButtonDrawable != null) mButtonDrawable.jumpToCurrentState();
456 }
457
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800458 static class SavedState extends BaseSavedState {
459 boolean checked;
460
461 /**
462 * Constructor called from {@link CompoundButton#onSaveInstanceState()}
463 */
464 SavedState(Parcelable superState) {
465 super(superState);
466 }
467
468 /**
469 * Constructor called from {@link #CREATOR}
470 */
471 private SavedState(Parcel in) {
472 super(in);
473 checked = (Boolean)in.readValue(null);
474 }
475
476 @Override
477 public void writeToParcel(Parcel out, int flags) {
478 super.writeToParcel(out, flags);
479 out.writeValue(checked);
480 }
481
482 @Override
483 public String toString() {
484 return "CompoundButton.SavedState{"
485 + Integer.toHexString(System.identityHashCode(this))
486 + " checked=" + checked + "}";
487 }
488
489 public static final Parcelable.Creator<SavedState> CREATOR
490 = new Parcelable.Creator<SavedState>() {
491 public SavedState createFromParcel(Parcel in) {
492 return new SavedState(in);
493 }
494
495 public SavedState[] newArray(int size) {
496 return new SavedState[size];
497 }
498 };
499 }
500
501 @Override
502 public Parcelable onSaveInstanceState() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800503 Parcelable superState = super.onSaveInstanceState();
504
505 SavedState ss = new SavedState(superState);
506
507 ss.checked = isChecked();
508 return ss;
509 }
510
511 @Override
512 public void onRestoreInstanceState(Parcelable state) {
513 SavedState ss = (SavedState) state;
514
515 super.onRestoreInstanceState(ss.getSuperState());
516 setChecked(ss.checked);
517 requestLayout();
518 }
519}