分析ScrollView嵌套RecyclerView、ViewPager引起的滑動問題

有些需求要在一個頁面裏面加好多東西,因而會出現嵌套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處理觸摸事件,得具體分析,照搬多是不行的事件

相關文章
相關標籤/搜索