1.点击事件的传递规则
点击事件的分发过程是由三个很重要的方法来共同完成
@Override
public boolean
dispatchTouchEvent
(MotionEvent ev) {
return super
.dispatchTouchEvent(ev)
;
}
@Override
public boolean
onInterceptTouchEvent
(MotionEvent ev) {
return super
.onInterceptTouchEvent(ev)
;
}
@Override
public boolean
onTouchEvent
(MotionEvent event) {
return super
.onTouchEvent(event)
;
}
public boolean dispatchTouchEvent(MotionEvent ev){}
用来进行事件分发。如果事件能够传递给当前view,那么此方法一定会被调用,返回结果受当前view的onTouchEvent和下级的dispatchTouchEvent方法影响,表示是否消耗当前事件
public boolean onInterceptTouchEvent(MotionEvent event){}
内部调用,用来判断是否拦截某个事件,如果当前view拦截了某个事件,那么在同一个事件序列当中,此方法不会被再次调用,返回结果表示是否拦截当前事件
public boolean onTouchEvent(MotionEvent event){}
在
dispatchTouchEvent方法内部被调用,
onTouchEvent
用来处理触摸事件,返回结果表示是否消耗当前事件,如果不消耗,则在同一个事件序列中,当前view无法再次接收到事件
画了个流程图如下:
一个触摸事件产生后,它的传递顺序如下:Activity->Window->View
- onClick会发生的前提是当前View是可点击的,并且它收到了down和up的事件
- 事件传递过程是由外向内的,事件总是先传递给父元素,然后由父元素分发给子View,通过requestDisallowInterceptTouchEvent方法可以在子元素中干预父元素的事件分发过程,但是ACTION_DOWN事件除外
滑动事件冲突
- 父容器左右滑动 与子元素上下滑动冲突
- 父容器与子元素滑动方向相同时滑动冲突
- 以上场景综合
解决滑动冲突的方法:
1.外部拦截法
重写父容器onInterceptTouchEvent方法
滑动冲突场景:
父容器左右滑动 与子元素上下滑动
可以根据水平方向和竖直方向直接的距离差进行判断 是否需要拦截此滑动事件
@Override
public boolean
onInterceptTouchEvent
(MotionEvent ev) {
switch
(ev.getAction()){
case
MotionEvent.
ACTION_MOVE
:
if
(
"父容器需要在onTouchEvent方法里面处理的事件"
){
return true;
}
else
{
return false;
}
break;
default
:
break;
}
return super
.onInterceptTouchEvent(ev)
;
}
2.内部拦截法
父容器不拦截除了ACTION_DOWN以外的任何事件
为何不能拦截
ACTION_DOWN事件?因为如果拦截
ACTION_DOWN事件后 事件将不会传递给子元素
@Override
public boolean
onInterceptTouchEvent
(MotionEvent ev) {
if
(ev.getAction()==MotionEvent.
ACTION_DOWN
){
return false;
}
else
{
return true;
}
}
内部子元素重写
dispatchTouchEvent方法
@Override
public boolean
dispatchTouchEvent
(MotionEvent ev) {
switch
(ev.getAction()){
case
MotionEvent.
ACTION_DOWN
:
getParent().requestDisallowInterceptTouchEvent(
true
)
;
break;
case
MotionEvent.
ACTION_MOVE
:
if
(
"父容器需要在onTouchEvent方法里面处理的事件"
){
getParent().requestDisallowInterceptTouchEvent(
false
)
;
//不干预父类的拦截事件
}
break;
case
MotionEvent.
ACTION_UP
:
break;
default
:
break;
}
return super
.dispatchTouchEvent(ev)
;
}