打到最后,应该就剩你自己,和,你为的人吧。 —— 聛 《自创》
本文可解决外部ViewPager和内部ViewPager左右滑动的冲突事件。
外层内层ViewPager都是左右滑动,不做处理,Android分不清到底是谁滑动,所以会出现滑动冲突。
首先我们先上完成效果图
事件分发理解
那么该如何解决滑动冲突呢?
在此之前我们需要知道Android的事件分发机制。
在这里不追溯源码,只说结论,源码分析有时间在写。
事件分发由Activity->ViewGrop->View
上图理解:(网上大佬的图)
这是Android事件分发的整体流程
这里涉及到三个方法:
dispatchTouchEvent() //分发事件
oninterceptTouchEvent() //事件拦截 ViewGrop专有
ontouchEvent() //处理事件
在这里对三个方法进行简单分析:
dispatchTouchEvent()返回true表示事件被消费事件停止分发,逐层向上返回 后续事件会继续分发给到该view;返回false 表示 当前事件没有被消费 则事件回传给上层的ontouchevent()处理,返回super下发给子View。
onInterceptTouchEvent()返回true表示当前的事件被ViewGroup拦截 则事件停止往下传递 ViewGroup自己处理事件,调用父类的super.dispatchTouchEvent(),最终执行自己的onTouchEvent();
返回false或者super 表示当前事件没有被ViewGroup拦截 则事件继续往下传递 事件传递到子view,调用view.dispatchTouchEvent()方法中去处理。
ontouchEvent()返回true当前使用对象处理了当前事件,事件停止分发,逐层往dispatchTouchEvent()方法中去处理;返回false 当前使用的对象没有处理事件,将事件向上传给上层的onTouchEvent()处理。
回归题目,我们该如何解决滑动冲突呢
实现思路
我们只需要在重写内层ViewPager的OnTouchEvent()事件,自己处理自己的点击滑动事件即可,不是自己的都交由上层ViewPager处理。
代码如下:
public class CustomViewPage extends ViewPager {
public CustomViewPage(@NonNull Context context) {
super(context);
}
public CustomViewPage(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent arg0) {
// 当拦截触摸事件到达此位置的时候,返回true,
// 说明将onTouch拦截在此控件,进而执行此控件的onTouchEvent
return true;
}
@Override
public boolean onTouchEvent(MotionEvent arg0) {
// TODO Auto-generated method stub
// 每次进行onTouch事件都记录当前的按下的坐标
switch (arg0.getAction()) {
case MotionEvent.ACTION_DOWN:
getParent().requestDisallowInterceptTouchEvent(true);//这句话是告诉父view,我的事件自己处理 不让父view拦截自己的事件
break;
case MotionEvent.ACTION_MOVE:
getParent().requestDisallowInterceptTouchEvent(true);
break;
case MotionEvent.ACTION_CANCEL:
getParent().requestDisallowInterceptTouchEvent(false);//这句话是告诉父view可以阻止我拦截我
break;
}
return super.onTouchEvent(arg0);
}
到这里就解决了。
同理处理ViewPager和ListView的滑动冲突也是同样的道理:重写ViewPager的OnInterceptTouchEvent()方法,判断滑动方向是否为左右,如果为左右则返回True,拦截交给父类执行自己的OntouchEvent()方法,否则下发给ListView。比较简单这里就不在演示了。