发布时间:2017-11-28责任编辑:朱明 浏览:10481
Android开发中经常碰到滑动冲突的问题,比如RecyclerView等垂直刷新的控件内嵌ViewPager,当手指斜着滑动RecyclerView时,便会引起RecyclerView的刷新,两者出现了滑动冲突,解决的方法如下:
1:从RecyclerView的角度出发:
Android的事件分发是从下到上的,父布局先分发到触摸事件,所以可以此时在父布局的
onInterceptTouchEvent中判断,当x轴的滑动距离大于y轴的滑动距离时,不拦截事件,
将事件交给子View去处理。
2:从ViewPager的角度出发:
同理,不处理父View,当x轴的滑动距离大于y轴的滑动距离时拦截事件,同时告诉父View不要拦截,代码如下:
/**
* 事件拦截
* @param ev
* @return
*/
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
int x = (int)ev.getX();
int y = (int)ev.getY();
switch (ev.getAction()){
case MotionEvent.ACTION_DOWN:
Log.i("CustomViewPager:","Intercept_ACTION_DOWN");
mLastX = x;
mLastY = y;
break;
case MotionEvent.ACTION_MOVE:
Log.i("CustomViewPager:","Intercept_ACTION_MOVE");
int dx = Math.abs(x - mLastX);
int dy = Math.abs(y - mLastY);
if(dx * 4 > dy){
// 上一页
if(x >= mLastX){
return ViewCompat.canScrollHorizontally(this,-1);
}else {
// 下一页
return ViewCompat.canScrollHorizontally(this,1);
}
}
break;
}
return super.onInterceptTouchEvent(ev);
}
/**
* 事件分发
* @param ev
* @return
*/
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
int x = (int)ev.getX();
int y = (int)ev.getY();
switch (ev.getAction()){
case MotionEvent.ACTION_DOWN:
Log.i("CustomViewPager:","dispatch_ACTION_DOWN");
mLastX = x;
mLastY = y;
getParent().requestDisallowInterceptTouchEvent(true);
break;
case MotionEvent.ACTION_MOVE:
Log.i("CustomViewPager:","dispatch_ACTION_MOVE");
int dx = Math.abs(x - mLastX);
int dy = Math.abs(y - mLastY);
if(dx * 4 > dy){
if(x >= mLastX){
// 上一页
if(ViewCompat.canScrollHorizontally(this,-1)){
getParent().requestDisallowInterceptTouchEvent(true);
}else {
getParent().requestDisallowInterceptTouchEvent(false);
}
}else {
// 下一页
if(ViewCompat.canScrollHorizontally(this,1)){
getParent().requestDisallowInterceptTouchEvent(true);
}else {
getParent().requestDisallowInterceptTouchEvent(false);
}
}
}else {
getParent().requestDisallowInterceptTouchEvent(false);
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
Log.i("CustomViewPager:","ACTION_UP/ACTION_CANCEL");
getParent().requestDisallowInterceptTouchEvent(false);
break;
}
return super.dispatchTouchEvent(ev);
}
同时重写dispatchTouchEvent与onInterceptTouchEvent,getParent().requestDisallowInterceptTouchEvent(true);用于告诉父View不要拦截此次触摸事件,ViewCompat.canScrollHorizontally(this,-1);用于判断ViewPager是否滑动到了左右边界,以防ViewPager内嵌ViewPager时滑动到边界后不能继续滑动的问题。
诚信工作室 供稿