blob: f5a0b1c09f1edfd0fe33925b9ed181f3eb4ed6a3 [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
19import android.content.Context;
20import android.content.res.TypedArray;
21import android.graphics.Canvas;
22import android.graphics.drawable.Drawable;
23import android.util.AttributeSet;
24import android.view.Gravity;
25
26import com.android.internal.R;
27
28
29/**
30 * An extension to TextView that supports the {@link android.widget.Checkable} interface.
31 * This is useful when used in a {@link android.widget.ListView ListView} where the it's
32 * {@link android.widget.ListView#setChoiceMode(int) setChoiceMode} has been set to
33 * something other than {@link android.widget.ListView#CHOICE_MODE_NONE CHOICE_MODE_NONE}.
34 *
35 */
36public abstract class CheckedTextView extends TextView implements Checkable {
37 private boolean mChecked;
38 private int mCheckMarkResource;
39 private Drawable mCheckMarkDrawable;
40 private int mBasePaddingRight;
41 private int mCheckMarkWidth;
42
43 private static final int[] CHECKED_STATE_SET = {
44 R.attr.state_checked
45 };
46
47 public CheckedTextView(Context context) {
48 this(context, null);
49 }
50
51 public CheckedTextView(Context context, AttributeSet attrs) {
52 this(context, attrs, 0);
53 }
54
55 public CheckedTextView(Context context, AttributeSet attrs, int defStyle) {
56 super(context, attrs, defStyle);
57
58 TypedArray a = context.obtainStyledAttributes(attrs,
59 R.styleable.CheckedTextView, defStyle, 0);
60
61 Drawable d = a.getDrawable(R.styleable.CheckedTextView_checkMark);
62 if (d != null) {
63 setCheckMarkDrawable(d);
64 }
65
66 boolean checked = a.getBoolean(R.styleable.CheckedTextView_checked, false);
67 setChecked(checked);
68
69 a.recycle();
70 }
71
72 public void toggle() {
73 setChecked(!mChecked);
74 }
75
76 public boolean isChecked() {
77 return mChecked;
78 }
79
80 /**
81 * <p>Changes the checked state of this text view.</p>
82 *
83 * @param checked true to check the text, false to uncheck it
84 */
85 public void setChecked(boolean checked) {
86 if (mChecked != checked) {
87 mChecked = checked;
88 refreshDrawableState();
89 }
90 }
91
92
93 /**
94 * Set the checkmark to a given Drawable, identified by its resourece id. This will be drawn
95 * when {@link #isChecked()} is true.
96 *
97 * @param resid The Drawable to use for the checkmark.
98 */
99 public void setCheckMarkDrawable(int resid) {
100 if (resid != 0 && resid == mCheckMarkResource) {
101 return;
102 }
103
104 mCheckMarkResource = resid;
105
106 Drawable d = null;
107 if (mCheckMarkResource != 0) {
108 d = getResources().getDrawable(mCheckMarkResource);
109 }
110 setCheckMarkDrawable(d);
111 }
112
113 /**
114 * Set the checkmark to a given Drawable. This will be drawn when {@link #isChecked()} is true.
115 *
116 * @param d The Drawable to use for the checkmark.
117 */
118 public void setCheckMarkDrawable(Drawable d) {
119 if (d != null) {
120 if (mCheckMarkDrawable != null) {
121 mCheckMarkDrawable.setCallback(null);
122 unscheduleDrawable(mCheckMarkDrawable);
123 }
124 d.setCallback(this);
125 d.setVisible(getVisibility() == VISIBLE, false);
126 d.setState(CHECKED_STATE_SET);
127 setMinHeight(d.getIntrinsicHeight());
128
129 mCheckMarkWidth = d.getIntrinsicWidth();
130 mPaddingRight = mCheckMarkWidth + mBasePaddingRight;
131 d.setState(getDrawableState());
132 mCheckMarkDrawable = d;
133 } else {
134 mPaddingRight = mBasePaddingRight;
135 }
136 requestLayout();
137 }
138
139 @Override
140 public void setPadding(int left, int top, int right, int bottom) {
141 super.setPadding(left, top, right, bottom);
142 mBasePaddingRight = mPaddingRight;
143 }
144
145 @Override
146 protected void onDraw(Canvas canvas) {
147 super.onDraw(canvas);
148
149 final Drawable checkMarkDrawable = mCheckMarkDrawable;
150 if (checkMarkDrawable != null) {
151 final int verticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK;
152 final int height = checkMarkDrawable.getIntrinsicHeight();
153
154 int y = 0;
155
156 switch (verticalGravity) {
157 case Gravity.BOTTOM:
158 y = getHeight() - height;
159 break;
160 case Gravity.CENTER_VERTICAL:
161 y = (getHeight() - height) / 2;
162 break;
163 }
164
165 int right = getWidth();
166 checkMarkDrawable.setBounds(
167 right - mCheckMarkWidth - mBasePaddingRight,
168 y,
169 right - mBasePaddingRight,
170 y + height);
171 checkMarkDrawable.draw(canvas);
172 }
173 }
174
175 @Override
176 protected int[] onCreateDrawableState(int extraSpace) {
177 final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
178 if (isChecked()) {
179 mergeDrawableStates(drawableState, CHECKED_STATE_SET);
180 }
181 return drawableState;
182 }
183
184 @Override
185 protected void drawableStateChanged() {
186 super.drawableStateChanged();
187
188 if (mCheckMarkDrawable != null) {
189 int[] myDrawableState = getDrawableState();
190
191 // Set the state of the Drawable
192 mCheckMarkDrawable.setState(myDrawableState);
193
194 invalidate();
195 }
196 }
197
198}