您的位置:首页 > 其它

View的滑动冲突(通用解决方式)

2016-07-26 17:51 525 查看

View的滑动冲突

产生:界面中存在内外两层同时可以滑动的View

滑动冲突的场景

场景一:外部滑动方向和内部滑动方向不一致

场景二:外部滑动方向和内部滑动方向一致

场景三:上面两种情况的嵌套

滑动冲突的处理规则

根据滑动是水平滑动还是竖直滑动来判断到底由谁来拦截事件(适用场景一)

当处于某种状态时需要外部View响应用户的滑动,而处于另外一种状态时则需要内部View来响应View的滑动(适用场景二和场景三)

滑动冲突的解决方式

外部拦截法和内部拦截法

外部拦截法:事件都先经过父容器的拦截处理,如果父容器需要此事件就拦截,如果不需要就不拦截。外部拦截法需要重写父容器的onInterceptTouchEvent方法

//分别记录上次滑动的坐标(onInterceptTouchEvent)
private int mLastXIntercept = 0;
private int mLastYIntercept = 0;

public boolean onInterceptTouchEvent(MotionEvent event){

boolean intercepted = false;
int x = (int)event.getX();
int y = (int)event.getY();
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
intercepted = false;
break;
case MotionEvent.ACTION_MOVE:

int deltaX = x - mLastXIntercept;
int deltaY = y - mLastYIntercept;

if(父容器需要当前点击事件){
intercepted = true;
}else{
intercepted = false;
}
break;
case MotionEvent.ACTION_UP:
intercepted = false;
break;
default:
break;
}

mLastXIntercept = x;
mLastYIntercept = y;

return intercepted;

}


上述代码是外部拦截法的典型逻辑,针对不同的滑动冲突只需修改“父容器需要当前点击事件”这个条件即可

内部拦截法:指父容器不拦截任何事件,所有的事件都传递给子元素,如果子元素需要此事件就消费,否则就交由父容器进行处理。这种方法需要配合requestDisallowInterceptTouchEvent方法才能正常工作

//分别记录上次滑动的坐标
private int mLastX = 0;
private int mLastY = 0;

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:
int deltaX = x - mLastX;
int deltaY = y - mLastY;
if(父容器需要此类点击事件){
parent.requestDisallowInterceptTouchEvent(false);
}
break;
case MotionEvent.ACTION_UP:
break;
default:
break;
}

mLastX = x;
mLastY = y;

return super.dispatchTouchEvent(event);

}


上述代码是内部拦截法的典型代码,面对不同的滑动策略时只需要更改“父容器需要此类点击事件”这个条件即可

父元素所做的修改如下

public boolean onInterceptTouchEvent(MotionEvent event){
int action = event.getAction();
if(action == MotionEvent.ACTION_DOWN){
return false;
}else{
return true;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: