美文网首页
Android 中解决ViewPager嵌套RecyclerVi

Android 中解决ViewPager嵌套RecyclerVi

作者: 那一刻彷徨 | 来源:发表于2019-12-25 15:18 被阅读0次

    思路

    最近在项目中遇到这样一个需求:某个页面中有4个Fragment,使用的是viewpager实现的,在某个fragment中又有一个横向滑动的Recyclerview,当时心想,这个需求也不难啊,咔咔一顿响需求实现了,结果发现横向滑动Recyclerview时直接触发了外层ViewPager的滑动,滑动到下一个Fragment了,直接懵逼了,剧情不是这样的啊,然后一顿咔咔百度,发现还是有各种各样的问题,没办法,只能自己解决咯
    代码已经上传到github:project

    步骤

    1.自定view继承RecyclerView 重写dispatchTouchEvent
    2.监听手指移动方向 水平方向大于竖直方向 则禁止ViewPager的滑动 否则开启ViewPager的滑动以上步骤就是整个功能的核心思想,也算是一个取巧吧!

    核心代码

    重写Recyclerview触摸事件

    import android.content.Context;
    import android.support.annotation.Nullable;
    import android.support.v4.widget.SwipeRefreshLayout;
    import android.support.v7.widget.RecyclerView;
    import android.util.AttributeSet;
    import android.view.MotionEvent;
    import android.view.ViewParent;
    
    import com.apkfuns.logutils.LogUtils;
    import com.meetacg.widget.pager.NoScrollViewPager;
    
    /**
     * @author ganhuanhui
     * 时间:2019/12/2 0002
     * 描述:
     */
    public class HorizontalRecyclerView extends RecyclerView {
    
        private float x1;
        private float y1;
        private SwipeRefreshLayout mSwipeRefreshLayout;
    
        public HorizontalRecyclerView(Context context) {
            super(context);
        }
    
        public HorizontalRecyclerView(Context context, @Nullable AttributeSet attrs) {
            super(context, attrs);
        }
    
        public HorizontalRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
        }
        @Override
        public boolean dispatchTouchEvent(MotionEvent event) {
            //解决recyclerView和viewPager的滑动影响
            //当滑动recyclerView时,告知父控件不要拦截事件,交给子view处理
            get(false);
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    //当手指按下的时候
                    x1 = event.getX();
                    y1 = event.getY();
                    break;
                case MotionEvent.ACTION_MOVE:
                    //当手指移动的时候
                    float x2 = event.getX();
                    float y2 = event.getY();
                    float offsetX = Math.abs(x2 - x1);
                    float offsetY = Math.abs(y2 - y1);
                    if (offsetX >= offsetY) {
                        get(true);//手指左移
                    } else {
                        get(false);
                    }
                    break;
                case MotionEvent.ACTION_UP:
                    x1 = y1 = 0;
                    get(false);
                    break;
            }
            return super.dispatchTouchEvent(event);
        }
    
        private ViewParent mViewParent;
    
        //使用迭代 直至找到parent是NoScrollViewPager为止
        //效率有些低 偏low 莫见怪
        private void get(boolean isEnable) {
            if (mViewParent == null)
                mViewParent = getParent();
            else
                mViewParent = mViewParent.getParent();
            if (mViewParent instanceof NoScrollViewPager) {
                //true 禁止ViewPager滑动,自动交给recyclerview去滑动
                //false 交给ViewPager滑动
                NoScrollViewPager viewPager = (NoScrollViewPager) mViewParent;
                viewPager.setNoScroll(isEnable);
    
            } else {
                get(isEnable);
            }
        }
    }
    

    //重写ViewPager onTouchEvent onInterceptTouchEvent

    import android.content.Context;
    import android.support.v4.view.ViewPager;
    import android.util.AttributeSet;
    import android.view.MotionEvent;
    
    /**
     * @author ganhuanhui
     * 时间:2019/12/17 0017
     * 描述:可禁止滑动的ViewPager
     */
    public class NoScrollViewPager extends ViewPager {
        // 是否禁止 viewpager 左右滑动
        private boolean noScroll = false;
    
        public void setNoScroll(boolean noScroll){
            this.noScroll = noScroll;
        }
    
        public NoScrollViewPager(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        @Override
        public boolean onTouchEvent(MotionEvent arg0) {
            if (noScroll){
                return false;
            }else{
                return super.onTouchEvent(arg0);
            }
        }
    
        @Override
        public boolean onInterceptTouchEvent(MotionEvent arg0) {
            if (noScroll){
                return false;
            }else{
                return super.onInterceptTouchEvent(arg0);
            }
        }
    
    }
    
    

    使用

    把HorizontalRecyclerView当做正常的Recyclerview使用即可
    好了,大功告成,目前已经用在项目中 暂无发现问题 如有发现问题的朋友 还请私聊告知

    参考

    Android禁止滑动的NoScrollViewPager

    Android 网格分页布局

    相关文章

      网友评论

          本文标题:Android 中解决ViewPager嵌套RecyclerVi

          本文链接:https://www.haomeiwen.com/subject/lxpcoctx.html