浅谈android view事件分发机制
对于android开发人员来说,事件分发机制肯定是熟悉的,由于近期看了事件分发机制方面的资料,决定自己来梳理下,顺便分享出来,希望看客多多包容,有错之处帮忙指出。
有一个小的例子,我们给button设置点击事件,在onClick方法中执行我们想要的操作,这个听起来非常的平常,但是我们在这个基础上应该要知道到底层的原理是什么,掌握了原理后更加利益今后的开发。
做一个简单的例子,以下直接贴出代码
public class MyButton extends Button {
private static final String TAG = MyButton.class.getSimpleName();
public MyButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
Log.e(TAG, "onTouchEvent DOWN");
break;
case MotionEvent.ACTION_MOVE:
Log.e(TAG,"OnTouchEvent MOVE");
break;
case MotionEvent.ACTION_UP:
Log.e(TAG,"onTouchEvent UP");
break;
}
return super.onTouchEvent(event);
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
int action = event.getAction();
switch (action){
case MotionEvent.ACTION_DOWN:
Log.e(TAG,"dispatchTouchEvent DOWN");
break;
case MotionEvent.ACTION_MOVE:
Log.e(TAG,"dispatchTouchEvent MOVE");
break;
case MotionEvent.ACTION_UP:
Log.e(TAG,"dispatchTouchEvent UP");
break;
}
return super.dispatchTouchEvent(event);
}
}
以上的代码比较简答,一看就明白了,代码中只是复写了onTouchEvent,dispatchTouchEvent这两个方法,并在其中打印了一些具体的操作,在布局中运用MyButton控件,在MainActivity中给 button设置触摸事件,也设置相应的打印
btn.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
int action = event.getAction();
switch (action){
case MotionEvent.ACTION_DOWN:
Log.e(TAG,"onTouch DOWN");
break;
case MotionEvent.ACTION_MOVE:
Log.e(TAG,"onTouch MOVE");
break;
case MotionEvent.ACTION_UP:
Log.e(TAG,"OnTouch UP");
break;
}
return false;
}
});
运行后可以看出给控件设置触摸事件执行的顺序,运行的顺序如下:
E/MyButton﹕ dispatchTouchEvent DOWN
E/TestActivity﹕ onTouch DOWN
E/MyButton﹕ onTouchEvent DOWN
E/MyButton﹕ dispatchTouchEvent UP
E/TestActivity﹕ OnTouch UP
E/MyButton﹕ onTouchEvent UP
在这里清晰的看出来运行的顺序。
其实可以去看看dispatchTouchEvent 的源码,源码在View类中
public boolean dispatchTouchEvent(MotionEvent event) {
if (!onFilterTouchEventForSecurity(event)) {
return false;
}
if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED &&
mOnTouchListener.onTouch(this, event)) {
return true;
}
return onTouchEvent(event);
}
其实只看中间的判断便明白了,其中有三个判断,这里分位三部:
1、判断给控件设置触摸事件不为空
2、该控件是否为激活的状态
3、该控件正在被触摸
满足了以上三点则给你返回true,否则执行onTouchEvent方法,这便是一般控件的触摸事件的原理。
在此基础上可以对一个控件进行多种事件监听,如点击,长按,触摸等,分别在其方法上进行打印输出就能看出结果。