码农翻身

Android处理ViewPager滑动冲突

- by MRyan, 2020-03-19


本文可解决外部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。比较简单这里就不在演示了。

作者:MRyan


本文采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。
转载时请注明本文出处及文章链接。本文链接:https://wormholestack.com/archives/195/
2025 © MRyan 36 ms