1.解决滑动冲突是有固定的模式,常见的有内部拦截和外部拦截,只要按照这俩种模式就可以顺利解决。
处理规则
对于场景1,处理规则为:当用户左右滑动时,让外部的View拦截点击事件,当用户上下滑动时,让内部的View拦截点击事件。当产生滑动时,根据滑动的起始点与终点坐标位置,如果垂直方向滑动距离大,就判断为垂直滑动,否则判断为水平滑动。其他两种情况处理方法相似,都是从业务需求上得出相应的规则。
外部拦截发
所有的点击事件都先经过父容器拦截处理,如果父容器需要拦截就拦截,不需要就传给内部的View。伪代码如下
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
|
<code
class
=
"language-java hljs "
>
public
boolean
onInterceptTouchEvent(MotionEvent event) {
boolean
intercepted =
false
;
switch
(event.getAction()) {
case
MotionEvent.ACTION_DOWN: {
intercepted =
false
;
break
;
}
case
MotionEvent.ACTION_MOVE: {
if
(满足父容器的拦截要求(getX()>getY())) {
intercepted =
true
;
}
else
{
intercepted =
false
;
}
break
;
}
case
MotionEvent.ACTION_UP: {
intercepted =
false
;
break
;
}
default
:
break
;
}
mLastXIntercept = x;
mLastYIntercept = y;
return
intercepted;
}</code>
|
注:
ACTION_DOWN这个事件是不能拦截的,因为一旦拦截后续的事件都会由父容器处理了。
内部拦截法
父容器不拦截任何事件,所有事件都传给子元素。如果子元素需要此事件就直接消耗,否则就交给父容器进行处理。完成这个功能需要配合requestDisallowInterceptTouchEvent()方法才可。这个方法表示是否让父容器拦截事件。伪代码如下:
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
|
<code
class
=
"language-java hljs "
>
public
boolean
dispatchTouchEvent(MotionEvent event) {
int
x = (
int
) event.getX();
int
y = (
int
) event.getY();
switch
(event.getAction()) {
case
MotionEvent.ACTION_DOWN: {
parent.requestDisallowInterceptTouchEvent(
true
);
break
;
}
case
MotionEvent.ACTION_MOVE: {
if
(满足父容器的拦截要求) {
parent.requestDisallowInterceptTouchEvent(
false
);
}
break
;
}
case
MotionEvent.ACTION_UP: {
break
;
}
default
:
break
;
}
mLastX = x;
mLastY = y;
return
super
.dispatchTouchEvent(event);
}</code>
|
注
父容器默认拦截除了ACTION_DOWN以外的其他事件,这样子当元素调用parent.requestDisallowInterceptTouchEvent(false)时,父元素才能拦截所需的事件。