代码地址:
https://github.com/VIVILL/SimpleDemo/tree/main/ViewPager2/slideconflict
当使用viewpager2+TabLayout + recyclerview 的时候,recyclerview上拉时,由于viewpager2灵敏度较高,容易造成 外层 viewpager2 横向滑动,导致 TabLayout 切换。
结构如下所示:
此时需要禁止viewpager2 滑动。
解决思路:
自定义recyclerview,重写dispatchTouchEvent,将MotionEvent数据回传给使用recyclerview的fragment,通过activityViewModels在fragment之间共享viewmodel,在HomeFragment中,当横向移动大小小于竖向移动大小时,禁止viewpager2滑动,从而降低ViewPager2灵敏度。
class TouchEventRecyclerView: RecyclerView {
constructor(context: Context) : super(context) {}
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {}
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
context,
attrs,
defStyleAttr
) {
}
private lateinit var onTouchEventListener: (ev: MotionEvent) -> Unit
fun setTouchEventListener(onTouchEventListener : (ev: MotionEvent) -> Unit){
this.onTouchEventListener = onTouchEventListener
}
override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
Log.d(TAG,"inner dispatchTouchEvent")
// 将 MotionEvent 回传
onTouchEventListener(ev)
return super.dispatchTouchEvent(ev)
}
}
定义viewmodel。
class TouchViewModel: ViewModel() {
private val _recyclerviewTouchAction = MutableSharedFlow<TouchAction>()
val recyclerviewTouchAction: SharedFlow<TouchAction> = _recyclerviewTouchAction
fun touchRecyclerview(event: MotionEvent) {
viewModelScope.launch {
_recyclerviewTouchAction.emit(TouchAction.Touch(event))
}
}
}
sealed class TouchAction {
data class Touch(val event: MotionEvent): TouchAction()
}
将事件回传。
// FirstFragment.kt
binding.recyclerview.setTouchEventListener{
Log.d(TAG,"inner setTouchEventListener")
viewModel.touchRecyclerview(it)
}
在TabLayout所在的fragment,订阅事件,增加合适的判断条件,这里是当横向移动大小小于竖向移动大小时,禁止viewpager2滑动。
// HomeFragment
private fun subscribeUI() {
viewLifecycleOwner.lifecycleScope.launch(exceptionHandler){
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.recyclerviewTouchAction.collect {
when (it) {
is TouchAction.Touch -> {
Log.d(TAG, "inner Touch")
when (it.event.action) {
MotionEvent.ACTION_DOWN -> {
Log.d(TAG, "inner MotionEvent.ACTION_DOWN")
startX = it.event.x.toInt()
startY = it.event.y.toInt()
Log.d(TAG,"ACTION_DOWN startX = $startX startY = $startY ")
}
MotionEvent.ACTION_MOVE -> {
val endX = it.event.x.toInt()
val endY = it.event.y.toInt()
val disX = abs(endX - startX)
val disY = abs(endY - startY)
if (disX < disY) {
binding.viewPager2.isUserInputEnabled = false
Log.d(TAG, "inner ACTION_MOVE binding.viewPager2.isUserInputEnabled = false")
}
}
MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL-> {
Log.d(TAG, "inner MotionEvent.ACTION_UP or ACTION_CANCEL binding.viewPager2.isUserInputEnabled = true")
startX = 0
startY = 0
binding.viewPager2.isUserInputEnabled = true
}
else -> {}
}
}
}
}
}
}
}
参考链接:
YuLook-解决ViewPager2滑动灵敏问题
https://www.jianshu.com/p/42d05885461a
网友评论