全網最全解決ViewPager橫向的ViewGroup滑動衝突的問題,例如RecyclerView等
之所以說是全網最全是因為搜尋了很多資料並沒有一個很好的解決方案,只是解決部分的bug,在此做一下整理如下:
首先專案中的需求介面結構是這樣的我Fragment最外層使用的RecyclerView,然後RecyclerView列表中展示的各種各樣的佈局,實現效果圖如下

image.png
底部有三個tab嵌套了三個fragment, fragment中又使用的RecyclerView實現列表資料展示。
遇到的問題如下:
-
底部列表item顯示不全,只能顯示一平的item,原因是最外層是一個RecyclerView導致事件滑動衝突把事件消費掉了,使底部的RecyclerView無法拿到事件,無法滑動。
解決方案:重寫底部三個tab中巢狀的RecyclerView,重寫onTouchEvent和dispatchTouchEvent目的是告訴父的RecyclerView我用事件的時候不要給我攔截,我用完之後你再攔截
直接上程式碼:
package com.tengniu.p2p.tnp2p.util.findfragment import android.content.Context import android.support.annotation.Nullable import android.view.MotionEvent import android.view.ViewConfiguration import android.support.v7.widget.RecyclerView import android.util.AttributeSet import android.util.Log /** * 作者:yshr on 2018/9/27 08:58 * RecycelView巢狀RecycelView * 解決發現頁面底部巢狀的RecycelView衝突的問題 */ class CustomRecyclerView : RecyclerView { private var mTouchSlop: Int = 0 internal var move_x: Int = 0 internal var move_y: Int = 0 internal var x = 0f//初始化按下時座標變數 internal var y = 0f//初始化按下時座標變數 constructor(context: Context) : super(context) { val vc = ViewConfiguration.get(context) mTouchSlop = vc.scaledTouchSlop } constructor(context: Context, @Nullable attrs: AttributeSet) : super(context, attrs) { val vc = ViewConfiguration.get(context) mTouchSlop = vc.scaledTouchSlop } override fun onTouchEvent(e: MotionEvent): Boolean { Log.e("motion_event_mTouchSlop", mTouchSlop.toString()) when (e.action) { MotionEvent.ACTION_DOWN -> { move_x = e.x.toInt() move_y = e.y.toInt() parent.requestDisallowInterceptTouchEvent(true) Log.e("motion_event", "downx==y$move_x ==== $move_y") } MotionEvent.ACTION_MOVE -> { Log.e("motion_event", "movex==y$move_x ==== $move_y") val y = e.y.toInt() val x = e.x.toInt() if (Math.abs(y - move_y) > mTouchSlop || Math.abs(x - move_x) < mTouchSlop * 2) { parent.requestDisallowInterceptTouchEvent(false) } else { //告訴父控制元件不要攔截 子控制元件的操作 parent.requestDisallowInterceptTouchEvent(true) } } MotionEvent.ACTION_UP -> { performClick() //parent.requestDisallowInterceptTouchEvent(true) Log.e("motion_event", "upx==y$move_x ==== $move_y") } } return super.onTouchEvent(e) } override fun dispatchTouchEvent(ev: MotionEvent?): Boolean { parent?.requestDisallowInterceptTouchEvent(true); return super.dispatchTouchEvent(ev); } }
注意點:也是容易進坑的點
MotionEvent.ACTION_UP方法中一定要 加上performClick()方法,因為如果你不加的話,你會發現你列表中的item是沒有點選事件的,即使是給設定監聽並沒有什麼卵用
因為自定義View中重寫onTouchEvent後設置點選監聽onClick()方法無效會引起衝突,衝突原因請檢視參考這篇文章 ofollow,noindex">https://www.jianshu.com/p/7d1e773d9955
OK了可以愉快的happy了。。。