android事件分发学习笔记
2020-03-22 本文已影响0人
heheworld
- 事件分发的载体主要有 activity,viewgroup,view。
- 事件分发的主要方法有 dispatchTouchEvent (事件分发),onInterceptTouchEvent(事件拦截),onTouchEvent(事件响应),
-
关于返回值
是boolean类型,如果返回true,表示事件被消费,不再往下一级传递,否则继续传递。如果都没有消费,最终会回到activity的onTouchEvent。
-
关于onInterceptTouchEvent
是viewgroup所特有的。
-
- 事件分发的对象是 MotionEvent 。
- 事件的序列,常见的就是action_down,move,up,cancel等等,
- 如果一个view决定拦截,那么着一个序列的事件都会交由它来处理,同时down事件以外的事件也不再调用onInterceptTouchEvent方法。
- 正常情况下一个事件序列的事件不会分由两个view处理(通过ontouchevent强行传递给其他view的另说)
- 如果view 不消费除down以外的事件,该事件会消失。
- 如果view拦截后,但是什么事件都不处理,该事件会交由它的父view处理。
- 事件分发的流程 从activity的dispatchTouchEvent开始,经过phonewindow,decorview,调用到viewgroup的dispatchTouchEvent方法,然后在这个方法里,根据Intercept的值,事件的action,以及对应的childview(根据点击的坐标,从上至下的顺序 获取Z坐标上的view的列表,再依据view的dispatchTouchEvent返回值,返回愿意消费此事件的childview),事件就这样被传递出去。
例子,viewgroup如果拦截某事件,则直接调用viewgroup的onTouchEvent,
如果不拦截某事件,则交由子view处理,调用子view的dispatchTouchEvent,然后再调用子view的onTouchEvent。 - 关于触摸事件跟点击事件的冲突,如果onTouchEvent 返回true 则事件被消费,不会再响应点击事件。只有返回false,才可以。
- 关于滑动冲突,可以通过外部拦截和内部拦截两种方式。
外部拦截,
重写父view的onInterceptTouchEvent 方法
伪代码
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
int action = ev.getAction();
boolean intercept = false;
switch (ev.getAction())
{
case MotionEvent.ACTION_DOWN:
intercept = false;
break;
case MotionEvent.ACTION_MOVE:
if(需要拦截)
{
intercept = true;
}
else
{
intercept = false;
}
break;
case MotionEvent.ACTION_UP:
intercept = false;
break;
}
}
内部拦截,
重写子view的dispatchTouchEvent方法,设置父viewgroup的requestDisallowInterceptTouchEvent 的参数来做控制,
伪代码如下:
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
switch (ev.getAction())
{
case MotionEvent.ACTION_DOWN:
parent.requestDisallowInterceptTouchEvent(false);
break;
case MotionEvent.ACTION_MOVE:
if(父类容器需要拦截)
{
parent.requestDisallowInterceptTouchEvent(true);
}
else
{
parent.requestDisallowInterceptTouchEvent(true);
}
break;
case MotionEvent.ACTION_UP:
break;
}
boolean flag = super.dispatchTouchEvent(ev);
return flag;
}