思路
最近在项目中遇到这样一个需求:某个页面中有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使用即可
好了,大功告成,目前已经用在项目中 暂无发现问题 如有发现问题的朋友 还请私聊告知