/
CompoundDrawablesTextView.java
324 lines (287 loc) · 10.1 KB
/
CompoundDrawablesTextView.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
package com.bobomee.blogdemos.view.compound;
import android.content.Context;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.TextView;
import com.bobomee.blogdemos.R;
public class CompoundDrawablesTextView extends TextView implements OnClickListener {
/**
* 各个方向的图片资源
**/
private Drawable mLeftDrawable;
private Drawable mTopDrawable;
private Drawable mRightDrawable;
private Drawable mBottomDrawable;
/**
* 各个方向的图片资源是否被touch
**/
private boolean mIsLeftTouched;
private boolean mIsTopTouched;
private boolean mIsRightTouched;
private boolean mIsBottomTouched;
/**
* Drawable可响应的点击区域x方向允许的误差,表示图片x方向的此范围内的点击都被接受
**/
private int mLazyX = 0;
/**
* Drawable可响应的点击区域y方向允许的误差,表示图片y方向的此范围内的点击都被接受
**/
private int mLazyY = 0;
/**
* 图片点击的监听器
**/
private DrawableClickListener mDrawableClickListener;
public CompoundDrawablesTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public CompoundDrawablesTextView(Context context, AttributeSet attrs) {
this(context, attrs, R.attr.Compound_Drawables_TextView_Style);
}
public CompoundDrawablesTextView(Context context) {
this(context, null);
}
/**
* 设置OnClickListener为当前的listener,即调用{@link CompoundDrawablesTextView#onClick(View)}函数
**/
private void init() {
super.setOnClickListener(this);
}
@Override
public void setCompoundDrawables(Drawable left, Drawable top, Drawable right, Drawable bottom) {
mLeftDrawable = left;
mTopDrawable = top;
mRightDrawable = right;
mBottomDrawable = bottom;
super.setCompoundDrawables(left, top, right, bottom);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// 在event为actionDown时标记用户点击是否在相应的图片范围内
if (event.getAction() == MotionEvent.ACTION_DOWN) {
resetTouchStatus();
if (mDrawableClickListener != null) {
mIsLeftTouched = touchLeftDrawable(event);
mIsTopTouched = touchTopDrawable(event);
mIsRightTouched = touchRightDrawable(event);
mIsBottomTouched = touchBottomDrawable(event);
}
}
return super.onTouchEvent(event);
}
@Override
public void onClick(View v) {
/**
* 按照左上右下的顺序响应第一个点击范围内的Drawable
*/
if (mDrawableClickListener != null) {
if (mIsLeftTouched) {
mDrawableClickListener.onClick(DrawableClickListener.DrawablePosition.LEFT);
} else if (mIsTopTouched) {
mDrawableClickListener.onClick(DrawableClickListener.DrawablePosition.TOP);
} else if (mIsRightTouched) {
mDrawableClickListener.onClick(DrawableClickListener.DrawablePosition.RIGHT);
} else if (mIsBottomTouched) {
mDrawableClickListener.onClick(DrawableClickListener.DrawablePosition.BOTTOM);
} else {
mDrawableClickListener.onClick(DrawableClickListener.DrawablePosition.TEXT);
}
}
}
@Override
protected void finalize() throws Throwable {
mRightDrawable = null;
mBottomDrawable = null;
mLeftDrawable = null;
mTopDrawable = null;
super.finalize();
}
/**
* 重置各个图片touch的状态
*/
private void resetTouchStatus() {
mIsLeftTouched = false;
mIsTopTouched = false;
mIsRightTouched = false;
mIsBottomTouched = false;
}
/**
* touch左边的Drawable
*
* @param event
* @return 是否在touch范围内
*/
private boolean touchLeftDrawable(MotionEvent event) {
if (mLeftDrawable == null) {
return false;
}
// 计算图片点击可响应的范围,计算方法见http://trinea.iteye.com/blog/1562388
int drawHeight = mLeftDrawable.getIntrinsicHeight();
int drawWidth = mLeftDrawable.getIntrinsicWidth();
int topBottomDis = (mTopDrawable == null ? 0 : mTopDrawable.getIntrinsicHeight())
- (mBottomDrawable == null ? 0 : mBottomDrawable.getIntrinsicHeight());
double imageCenterY = 0.5 * (this.getHeight() + topBottomDis);
Rect imageBounds = new Rect(this.getCompoundDrawablePadding() - mLazyX,
(int) (imageCenterY - 0.5 * drawHeight - mLazyY), this.getCompoundDrawablePadding()
+ drawWidth + mLazyX,
(int) (imageCenterY + 0.5 * drawHeight + mLazyY));
return imageBounds.contains((int) event.getX(), (int) event.getY());
}
/**
* touch上边的Drawable
*
* @param event
* @return 是否在touch范围内
*/
private boolean touchTopDrawable(MotionEvent event) {
if (mTopDrawable == null) {
return false;
}
int drawHeight = mTopDrawable.getIntrinsicHeight();
int drawWidth = mTopDrawable.getIntrinsicWidth();
int leftRightDis = (mLeftDrawable == null ? 0 : mLeftDrawable.getIntrinsicWidth())
- (mRightDrawable == null ? 0 : mRightDrawable.getIntrinsicWidth());
double imageCenterX = 0.5 * (this.getWidth() + leftRightDis);
Rect imageBounds = new Rect((int) (imageCenterX - 0.5 * drawWidth - mLazyX), this.getCompoundDrawablePadding()
- mLazyY,
(int) (imageCenterX + 0.5 * drawWidth + mLazyX), this.getCompoundDrawablePadding()
+ drawHeight + mLazyY);
return imageBounds.contains((int) event.getX(), (int) event.getY());
}
/**
* touch右边的Drawable
*
* @param event
* @return 是否在touch范围内
*/
private boolean touchRightDrawable(MotionEvent event) {
if (mRightDrawable == null) {
return false;
}
int drawHeight = mRightDrawable.getIntrinsicHeight();
int drawWidth = mRightDrawable.getIntrinsicWidth();
int topBottomDis = (mTopDrawable == null ? 0 : mTopDrawable.getIntrinsicHeight())
- (mBottomDrawable == null ? 0 : mBottomDrawable.getIntrinsicHeight());
double imageCenterY = 0.5 * (this.getHeight() + topBottomDis);
Rect imageBounds = new Rect(this.getWidth() - this.getCompoundDrawablePadding() - drawWidth - mLazyX,
(int) (imageCenterY - 0.5 * drawHeight - mLazyY),
this.getWidth() - this.getCompoundDrawablePadding() + mLazyX,
(int) (imageCenterY + 0.5 * drawHeight + mLazyY));
return imageBounds.contains((int) event.getX(), (int) event.getY());
}
/**
* touch下边的Drawable
*
* @param event
* @return 是否在touch范围内
*/
private boolean touchBottomDrawable(MotionEvent event) {
if (mBottomDrawable == null) {
return false;
}
int drawHeight = mBottomDrawable.getIntrinsicHeight();
int drawWidth = mBottomDrawable.getIntrinsicWidth();
int leftRightDis = (mLeftDrawable == null ? 0 : mLeftDrawable.getIntrinsicWidth())
- (mRightDrawable == null ? 0 : mRightDrawable.getIntrinsicWidth());
double imageCenterX = 0.5 * (this.getWidth() + leftRightDis);
Rect imageBounds = new Rect((int) (imageCenterX - 0.5 * drawWidth - mLazyX), this.getHeight()
- this.getCompoundDrawablePadding()
- drawHeight - mLazyY,
(int) (imageCenterX + 0.5 * drawWidth + mLazyX), this.getHeight()
- this.getCompoundDrawablePadding()
+ mLazyY);
return imageBounds.contains((int) event.getX(), (int) event.getY());
}
/**
* 图片点击的监听器
*
* @author Trinea 2012-5-3 下午11:45:41
*/
public interface DrawableClickListener {
/**
* 图片的位置
*/
enum DrawablePosition {
/**
* 图片在TextView的左部
**/
LEFT,
/**
* 图片在TextView的上部
**/
TOP,
/**
* 图片在TextView的右部
**/
RIGHT,
/**
* 图片在TextView的底部
**/
BOTTOM,
/**
* 点击的是文字
*/
TEXT
}
/**
* 点击相应位置的响应函数
*
* @param position
*/
void onClick(DrawablePosition position);
}
/**
* 得到Drawable可响应的点击区域x方向允许的误差
*
* @return the lazyX
*/
public int getLazyX() {
return mLazyX;
}
/**
* 设置Drawable可响应的点击区域x方向允许的误差
*
* @param lazyX
*/
public void setLazyX(int lazyX) {
this.mLazyX = lazyX;
}
/**
* 得到Drawable可响应的点击区域y方向允许的误差
*
* @return the lazyY
*/
public int getLazyY() {
return mLazyY;
}
/**
* 设置Drawable可响应的点击区域y方向允许的误差
*
* @param lazyY
*/
public void setLazyY(int lazyY) {
this.mLazyY = lazyY;
}
/**
* 设置Drawable可响应的点击区域x和y方向允许的误差
*
* @param lazyX
* @param lazyY
*/
public void setLazy(int lazyX, int lazyY) {
this.mLazyX = lazyX;
this.mLazyY = lazyY;
}
/**
* 设置图片点击的listener
*
* @param listener
*/
public void setDrawableClickListener(DrawableClickListener listener) {
this.mDrawableClickListener = listener;
}
}