有些需求要在一個頁面裏面加好多東西,因而會出現嵌套RecyclerView,ViewPager的狀況。
可是在嵌套以後,即便使用NestedScrollView也會出現一些問題,好比嵌套RecyclerView會出現滑動卡頓,嵌套ViewPager會出如今ViewPager區域沒法上下滑動的問題。
1.先來講一下嵌套ViewPager沒法上下滑動的問題
個人思路是能夠在dispatchTouchEvent方法裏面,在ACTION_DOWN的時候,記錄下y座標;而後在ACTION_MOVE的時候,經過y座標的差值,來決定是本身處理,仍是交給父控件ide
public boolean dispatchTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: downY = ev.getY(); break; case MotionEvent.ACTION_MOVE: if (Math.abs(ev.getY() - downY) > 50) { getParent().requestDisallowInterceptTouchEvent(false); return false; } break; }
這樣經過事件分發,把事件攔截交給父控件,能夠解決沒法上下滑動的問題。
2.再來講說嵌套RecyclerView出現滑動卡頓的問題
我按照處理ViewPager的方法,想去解決RecyclerView的問題,結果發現這樣不行,會產生好多問題。
而後查資料發現一個很簡單的方法,覆寫LinearLayoutManager的canScrollVertically方法,return false禁止豎直方向的滑動,試了一下果真能夠,滑的很順暢。
既然問題解決了,那麼爲何一樣的方法,能夠解決ViewPager的問題,對RecyclerView卻不行呢?
既然canScrollVertically方法能夠解決,那麼我想能夠從源碼中找canScrollVerticall方法的相關,就能夠找出來答案了。就去看了一下源碼,果真找到了答案。
源碼那麼多,怎麼找呢?我想既然是觸摸滑動的問題,那麼應該逃不出分發(dispatchTouchEvent)、攔截(onInterceptTouchEvent)、處理(onTouchEvent)的那三個關於觸摸的方法,就在RecyclerView裏面搜索canScrollVertically,定位到dispatchTouchEvent方法裏面,果真看到了spa
@Override public boolean onInterceptTouchEvent(MotionEvent e) { ...無關代碼省略... switch (action) { case MotionEvent.ACTION_DOWN: ...無關代碼省略... int nestedScrollAxis = ViewCompat.SCROLL_AXIS_NONE; if (canScrollHorizontally) { nestedScrollAxis |= ViewCompat.SCROLL_AXIS_HORIZONTAL; } if (canScrollVertically) { nestedScrollAxis |= ViewCompat.SCROLL_AXIS_VERTICAL; } startNestedScroll(nestedScrollAxis, TYPE_TOUCH); break; ...... case MotionEvent.ACTION_MOVE: { ...無關代碼省略... if (mScrollState != SCROLL_STATE_DRAGGING) { ...無關代碼省略... } } break; ...無關代碼省略... } return mScrollState == SCROLL_STATE_DRAGGING; }
原來在RecyclerView中,對滑動事件的方法,是在ACTION_DOWN中進行的。
那麼若是自定義RecyclerView的話,只要在ACTION_DOWN中進行處理就應該能夠了。code
/** * @author zhangyi * @date 2018/9/21 * 解決嵌套RecycleView出現滑動卡頓的問題 */ public class NestedRecycleView extends RecyclerView { public NestedRecycleView(Context context) { super(context); } public NestedRecycleView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); } public NestedRecycleView(Context context, @Nullable AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override public boolean onInterceptTouchEvent(MotionEvent e) { if (e.getAction()== MotionEvent.ACTION_DOWN) { return false; } return super.onInterceptTouchEvent(e); } @Override public boolean onTouchEvent(MotionEvent e) { if (e.getAction()== MotionEvent.ACTION_DOWN) { //這個得加上,表明本身處理點擊事件,否則點擊item會沒反應 return true; } return super.onTouchEvent(e); } }
看來對不一樣的View處理觸摸事件,得具體分析,照搬多是不行的事件