在專案中出現多重嵌套情況時,會出現無法滑動的場景,比如經常碰到的場景
ViewPager -> Fragment -> RecyclerView -> RecyclerView | ViewPager
最外層是一個可滑動的 tabLayout+ViewPager,ViewPager 中是多個 Fragment,Fragment 中是 RecyclerView,RecycleView 串列是一個多型別,內嵌多個橫向滑動串列
此時內嵌的 ViewPager 或者 RecyclerView,只要是橫向滑動,就會跟上層的 ViewPager 滑動起沖突,導致嵌套的串列無法滑動
常規做法就是攔截事件,或者直接在滑動監聽中消費事件,但是這種做法只會讓滑動失效,情況有下面幾種:
要么只能橫向滑動,無法在這塊區域上下滑動;
要么直接滑動失效,只有一個串列有滑動事件;
要么上下滑動或者左右滑動不連貫,內外串列滑動不絲滑;
如果直接攔截或者消費事件處理,這種處理過于粗暴,容易影響其它 View,并且就跟上面前兩種情況一樣,無法得兼,

要做到嵌套串列區域可以正常橫向滑動,外層串列可以正常滑動,上下串列可以正常滑動,就需要額外處理了;
這里不能直接攔截,因為嵌套層次多深時,直接攔截會影響其它事件的處理;
這里主要使用 requestDisallowInterceptTouchEvent(在攔截事件前面執行) 方法在 onTouchEvent 中處理;
系統 View 以及一些好的第三方控制元件都會根據情況處理滑動監聽,在 onTouchEvent 事件中做一些處理,所以在不攔截消費的前提下,又滿足了自身需求,又不影響其它 View;
而子 View 如果需要告知父容器放開攔截,就可以使用 requestDisallowInterceptTouchEvent 方法,讓父容器的攔截事件無法得到執行,
上層滑動串列存在各種滑動監聽處理,會在觸摸事件 onTouchEvent 中處理各種滑動邏輯,所以導致嵌套串列無法起作用,要處理滑動問題,需要在 onTouchEvent 事件中根據情況告知父容器,不做滑動處理
class NestedRecyclerView(context: Context, attrs: AttributeSet) : RecyclerView(context, attrs) { private var x1 = 0f private var y1 = 0f private var isScroll = false @SuppressLint("ClickableViewAccessibility") override fun onTouchEvent(evt: MotionEvent?): Boolean { evt?.let { var str = "" when (evt.action) { MotionEvent.ACTION_DOWN -> { x1 = evt.x y1 = evt.y } MotionEvent.ACTION_MOVE -> if (this.childCount > 1) { // 通知其父控制元件不攔截 val x2 = evt.x val y2 = evt.y if (x1 - x2 > 1) { str = "向右滑" parent.requestDisallowInterceptTouchEvent(true) isScroll = false } else if (x2 - x1 > 1) { str = "向左滑" parent.requestDisallowInterceptTouchEvent(true) isScroll = false } else if (y1 - y2 > 100) { parent.requestDisallowInterceptTouchEvent(false) str = "向上滑" isScroll = true } else if (y2 - y1 > 100) { parent.requestDisallowInterceptTouchEvent(false) str = "向下滑" isScroll = true } XLog.e("--== $x1 $x2 $str") return if (isScroll){ true }else{ super.onTouchEvent(evt) } } MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> { if (isScroll) { parent.requestDisallowInterceptTouchEvent(false) } else { parent.requestDisallowInterceptTouchEvent(true) } return if (isScroll){ true }else{ super.onTouchEvent(evt) } } } } return super.onTouchEvent(evt) } }
主要集中在觸摸事件,通過滑動的距離判斷滑動方向,如果是左右滑動串列,則告訴父容器不做處理,交給本身,如果是上下滑動串列,交給父容器處理,
要想滑動比較絲滑,內外串列互補影響,還需要在up事件中處理一下,
同理,ViewPager 也是一樣的處理,只需要繼承 ViewPager 就行,觸摸邏輯一樣,處理后,就如絲般柔順了,

轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/507282.html
標籤:其他
