问题描述
场景ViewPage2+Fragment+RecyclerView(我的项目里RecycleView外层还套了一层SmartRefreshLayout)
因ViewPage2滑动太灵敏,RecyclerView纵向倾斜滑动,触发ViewPage2横向滑动而导致的滑动冲突问题
解决方案:
纵向倾斜滑动时,其实纵向、横向这两个动作都已触发了,在横向灵敏度高的情况下,可通过给横向滑动设置一个最小临界条件,控制横向滑动的触发条件,不至于横向滑动那么灵敏。
因我的子布局是SmartRefreshLayout+RecycleView,如果你的子布局就只有RecycleView,只需将我下面自定义的CustomRefreshLayout 类里的SmartRefreshLayout替换成RecycleView就行。
kotlin
/**
* 解决ViewPage2内嵌RecyclerView时,因ViewPage2滑动太灵敏,RecyclerView纵向倾斜滑动,
* 触发ViewPage2横向滑动的滑动冲突问题
*/
class CustomRefreshLayout @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : SmartRefreshLayout(context, attrs, defStyleAttr) {
private var startX = 0f
private var startY = 0f
companion object {
const val MIN_DISTANCE = 100 // 设置一个最小滑动距离,以减少误判
}
override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
when (ev.action) {
MotionEvent.ACTION_DOWN -> {
startX = ev.x
startY = ev.y
parent.requestDisallowInterceptTouchEvent(true) // 初始按下时,不让父控件拦截
}
MotionEvent.ACTION_MOVE -> {
val endX = ev.x
val endY = ev.y
val disX = abs(endX - startX)
val disY = abs(endY - startY)
// 如果横向滑动距离大于纵向滑动距离,且大于设定的最小距离,则认为是水平滑动
if (disX > disY) {
Log.e("dispatchTouchEvent 横向滑动:", "disX= $disX disY= $disY")
// 判断左右滑动的灵敏度,当左右滑动距离大于100 允许父控件处理滑动。
if (disX > MIN_DISTANCE) {
parent.requestDisallowInterceptTouchEvent(false)
}
} else {
Log.e("dispatchTouchEvent 纵向滑动:", "disX= $disX disY= $disY")
// 纵向滑动,不让父控件拦截
parent.requestDisallowInterceptTouchEvent(true)
}
}
MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
// 触摸事件结束时恢复默认行为
parent.requestDisallowInterceptTouchEvent(false)
}
}
return super.dispatchTouchEvent(ev)
}
}
kotlin
<CustomRefreshLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</CustomRefreshLayout>