前沿:
很久没有写过博客了,因为工作的原因很少有时间写东西了,最近想写一个UI系列的博客,因为我发现这一系列的都很少,而且没有那么 系统 ,这里我想以我自己的观点来阐述一下如何自定义android 控件系列。自定义控件阐述:
在我的理解里面自定义控件,需要了解到touch事件的传递、分发、拦截机制,Scroller类的运用,andorid 视图的理解,ViewGroup的熟悉,因为我们绝大多的控件都是继承自ViewGroup,还有就是要学会布局测量等。Touch事件的传递
首先我们要了解在android系统里面有几个地方会走touch事件,这个是老生常谈的问题了,但是我还是希望写一下这个问题,因为温故而知新嘛,我们首先得知道VIew类这种不能作为容器的类只会有这两个函数:
1
2
3
4
5
6
7
8
9
10
11
|
@Override
public
boolean
dispatchTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
return
super
.dispatchTouchEvent(event);
}
@Override
public
boolean
onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
return
super
.onTouchEvent(event);
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
@Override
public
boolean
onInterceptTouchEvent(MotionEvent ev) {
// TODO Auto-generated method stub
return
super
.onInterceptTouchEvent(ev);
}
@Override
public
boolean
onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
return
super
.onTouchEvent(event);
}
@Override
public
boolean
dispatchTouchEvent(MotionEvent ev) {
// TODO Auto-generated method stub
return
super
.dispatchTouchEvent(ev);
}
|
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
|
public
class
MyTextView
extends
TextView{
private
final
String TAG = MyTextView.
class
.getSimpleName();
public
MyTextView(Context context) {
super
(context);
}
@Override
public
boolean
dispatchTouchEvent(MotionEvent event) {
switch
(event.getAction()) {
case
MotionEvent.ACTION_DOWN:
Log.d(TAG, TAG +
"dispatchTouchEvent+ACTION_DOWN"
);
break
;
case
MotionEvent.ACTION_POINTER_DOWN:
Log.d(TAG, TAG +
"dispatchTouchEvent+ACTION_POINTER_DOWN"
);
break
;
case
MotionEvent.ACTION_POINTER_UP:
Log.d(TAG, TAG +
"dispatchTouchEvent+ACTION_POINTER_UP"
);
break
;
case
MotionEvent.ACTION_MOVE:
Log.d(TAG, TAG +
"dispatchTouchEvent+ACTION_MOVE"
);
break
;
case
MotionEvent.ACTION_UP:
Log.d(TAG, TAG +
"dispatchTouchEvent+ACTION_UP"
);
break
;
}
return
super
.dispatchTouchEvent(event);
}
@Override
public
boolean
onTouchEvent(MotionEvent event) {
switch
(event.getAction()) {
case
MotionEvent.ACTION_DOWN:
Log.d(TAG, TAG +
"onTouchEvent+ACTION_DOWN"
);
break
;
case
MotionEvent.ACTION_POINTER_DOWN:
Log.d(TAG, TAG +
"onTouchEvent+ACTION_POINTER_DOWN"
);
break
;
case
MotionEvent.ACTION_POINTER_UP:
Log.d(TAG, TAG +
"onTouchEvent+ACTION_POINTER_UP"
);
break
;
case
MotionEvent.ACTION_MOVE:
Log.d(TAG, TAG +
"onTouchEvent+ACTION_MOVE"
);
break
;
case
MotionEvent.ACTION_UP:
Log.d(TAG, TAG +
"onTouchEvent+ACTION_UP"
);
break
;
}
return
super
.onTouchEvent(event);
}
}
|
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
|
public
class
MyLinearLayout
extends
LinearLayout {
private
final
String TAG = MyLinearLayout.
class
.getSimpleName();
public
MyLinearLayout(Context context) {
super
(context);
}
@Override
public
boolean
onInterceptTouchEvent(MotionEvent ev) {
switch
(ev.getAction()) {
case
MotionEvent.ACTION_DOWN:
Log.d(TAG, TAG +
"onInterceptTouchEvent+ACTION_DOWN"
);
break
;
case
MotionEvent.ACTION_POINTER_DOWN:
Log.d(TAG, TAG +
"onInterceptTouchEvent+ACTION_POINTER_DOWN"
);
break
;
case
MotionEvent.ACTION_POINTER_UP:
Log.d(TAG, TAG +
"onInterceptTouchEvent+ACTION_POINTER_UP"
);
break
;
case
MotionEvent.ACTION_MOVE:
Log.d(TAG, TAG +
"onInterceptTouchEvent+ACTION_MOVE"
);
break
;
case
MotionEvent.ACTION_UP:
Log.d(TAG, TAG +
"onInterceptTouchEvent+ACTION_UP"
);
break
;
}
return
super
.onInterceptTouchEvent(ev);
}
@Override
public
boolean
onTouchEvent(MotionEvent event) {
switch
(event.getAction()) {
case
MotionEvent.ACTION_DOWN:
Log.d(TAG, TAG +
"onTouchEvent+ACTION_DOWN"
);
break
;
case
MotionEvent.ACTION_POINTER_DOWN:
Log.d(TAG, TAG +
"onTouchEvent+ACTION_POINTER_DOWN"
);
break
;
case
MotionEvent.ACTION_POINTER_UP:
Log.d(TAG, TAG +
"onTouchEvent+ACTION_POINTER_UP"
);
break
;
case
MotionEvent.ACTION_MOVE:
Log.d(TAG, TAG +
"onTouchEvent+ACTION_MOVE"
);
break
;
case
MotionEvent.ACTION_UP:
Log.d(TAG, TAG +
"onTouchEvent+ACTION_UP"
);
break
;
}
return
super
.onTouchEvent(event);
}
@Override
public
boolean
dispatchTouchEvent(MotionEvent ev) {
switch
(ev.getAction()) {
case
MotionEvent.ACTION_DOWN:
Log.d(TAG, TAG +
"dispatchTouchEvent+ACTION_DOWN"
);
break
;
case
MotionEvent.ACTION_POINTER_DOWN:
Log.d(TAG, TAG +
"dispatchTouchEvent+ACTION_POINTER_DOWN"
);
break
;
case
MotionEvent.ACTION_POINTER_UP:
Log.d(TAG, TAG +
"dispatchTouchEvent+ACTION_POINTER_UP"
);
break
;
case
MotionEvent.ACTION_MOVE:
Log.d(TAG, TAG +
"dispatchTouchEvent+ACTION_MOVE"
);
break
;
case
MotionEvent.ACTION_UP:
Log.d(TAG, TAG +
"dispatchTouchEvent+ACTION_UP"
);
break
;
}
return
super
.dispatchTouchEvent(ev);
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
public
class
TestActivity
extends
Activity {
@Override
protected
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
MyLinearLayout layout =
new
MyLinearLayout(
this
);
MyTextView myTextView =
new
MyTextView(
this
);
myTextView.setText(
"touch event"
);
layout.addView(myTextView,
new
LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
setContentView(layout);
}
}
|
你会看到事件始终都只在MyLinearLayout里面了,根本就没有传递到孩子里面去了。同样我们把它返回false,试试
这时候看到只有down事件了,这说明了什么呢?当dispatchTouchEvent返回true的时候会继续传递事件给自身控件dispatchTouchEvent处理,就像刚才的MylinearLayout一样仍然可以执行,DOWN和UP事件,当我们返回了false就连自身控件都不能接收到事件了。同样我们把dispatchTouchEvent还原,然后在onInterceptTouchEvent里面返回true;
可以看到事件也只分发到自身控件并进入到自身的OntouchEvent中,然后我们在把onInterceptTouchEvent的返回值改为false,看看结果
可以看到我们的事件没有收到任何影响所有的都照常执行,同样把MylinearLayout中的onInterceptTouchEvent复原,现在注意了我们要修改的是MyTextView中的onTouchEvent的返回值,我们把它修改为true
可以看到也没有任何变化,我们在试试把它改为false。
可以看到MytextView只接收到DOWN事件就再也不会接收到其他事件了。