Android 中解决ViewPager嵌套RecyclerView滑动冲突

思路

最近在项目中遇到这样一个需求:某个页面中有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 网格分页布局

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值