Android RecycleView上下滑动带动ViewPage2左右滑动
程序员文章站
2022-07-02 23:34:35
一,问题描述:当页面是由导航栏TabLayout,ViewPage2 ,列表RecycleView 组成的时候,RecycleView上下滑动,总是不经意的带动了ViewPage2的左右滑动,ViewPage2太灵敏。解决问题方法核心:分发事件。 (其实看了一遍并没什么思路)思路:从布局开始:ViewPage2+Tablayout+Fragment而我们RecycleView是在Fragment中,Fragment又在ViewPage2中。也就是说ViewPage2是RecycleViewd...
一,问题描述:
当页面是由导航栏TabLayout,ViewPage2 ,列表RecycleView 组成的时候,RecycleView上下滑动,总是不经意的带动了ViewPage2的左右滑动,ViewPage2太灵敏。
-
解决问题方法核心:分发事件。 (其实看了一遍并没什么思路)
-
思路:从布局开始:ViewPage2+Tablayout+Fragment
而我们RecycleView是在Fragment中,Fragment又在ViewPage2中。也就是说ViewPage2是RecycleViewd的父布局。
然而,看了一下ViewPage2并不能被继承。 那我们可以做的就是,在RecycleView 滑动的时候,去影响ViewPage2 ,怎么去影响他呢?这是个问题。
先看下 子控件 的拦截方法都有啥
自定义View 继承 RecycleView 实现这个方法
这是RecycleView的事件分发方法,我们的操作就要在这个里面。
override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
when (ev!!.action) {
//按下
MotionEvent.ACTION_DOWN -> {
//此时,得到手指坐标 X,Y
}
//移动
MotionEvent.ACTION_MOVE -> {
//移动的距离
}
//这里 抬起手指,和取消动作。
MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
}
}
return super.dispatchTouchEvent(ev)
}
怎么操作父布局
下面这个接口→视图父类。
Defines the responsibilities for a class that will be a parent of a View.
This is the API that a view sees when it wants to interact with its parent.
解释:大概意思是,使用这个类,可以得到当前布局(使用这个方法的布局)的父布局。并与之交互。
public interface ViewParent {
//其他方法略
...
/**
* 这个方法:如果父元素存在,返回父元素;或者null。
*/
public ViewParent getParent();
/**
* 还有这个:当子View不希望被父View调用时使用,意思就是我自己来,不让父布局管。
* true:拦截,false:不拦截
*/
public void requestDisallowInterceptTouchEvent(boolean disallowIntercept);
...
}
以上就是关键的方法,下面,直接看完整代码
import android.content.Context
import android.util.AttributeSet
import android.util.Log
import android.view.MotionEvent
import android.view.ViewConfiguration
import androidx.recyclerview.widget.RecyclerView
import kotlin.math.abs
/**
* author : ChenWenJie
* email : 1181620038@qq.com
* date : 2020/7/29
* desc : 滑动冲突。斜着往上滑的时候,会滑动viewpage
*/
class MyRecyclerView(context: Context, attrs: AttributeSet?) : RecyclerView(context, attrs) {
private var mTouchSlop = 0
var startX = 0 //手指碰到屏幕时的 X坐标
var startY = 0 //手机碰到屏幕时的 Y坐标
init {
val vc = ViewConfiguration.get(context)
mTouchSlop = vc.scaledTouchSlop
}
override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
when (ev!!.action) {
MotionEvent.ACTION_DOWN -> {
//当手指按下时,得到了X,Y,
startX = ev!!.x.toInt()
startY = ev!!.y.toInt()
//
parent.requestDisallowInterceptTouchEvent(true)
}
MotionEvent.ACTION_MOVE -> {
//抬起手后得到的坐标,
val endX = ev!!.x.toInt()
val endY = ev!!.y.toInt()
//得到绝对值 。
val disX = abs(endX - startX)
val disY = abs(endY - startY)
//如果X轴 大于Y 轴,说明实在左右移动 为什么?
// 屏幕坐标,X,Y从左上角开始。0,0
if (disX > disY) {
Log.e("ACTIONdisX > disY:", "$disX")
//这个地方,判断了左右滑动的灵敏度,只有当左右滑动距离110 此时父布局才有作用,不拦截。
if (disX > 110) { //结束的时候大于
//当滑动的距离大于100的时候,才不拦截parent的事件 父控件才会有用。
parent.requestDisallowInterceptTouchEvent(false)
}
} else {
// 说明是上下滑动 //canScrollVertically 检查此视图是否可以按某个方向垂直滚动。 负数表示上下滚动。正数表示左右滚动
//return true如果视图可以按指定的方向滚动,否则为false。
//既然是上下滑动,此时,父控件就不能有 事件 true停止
parent.requestDisallowInterceptTouchEvent(true)
}
}
MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> parent.requestDisallowInterceptTouchEvent(false)
}
return super.dispatchTouchEvent(ev)
}
}
看下效果图:在这里插入图片描述
本文地址:https://blog.csdn.net/qq_26841579/article/details/107978339