Android中ViewPager帶來的滑動卡頓問題解決要點解析_Android

來源:互聯網
上載者:User

問題說明:
當SwipeRefreshLayout中放置了ViewPager控制項,兩者的滑動會相互衝突.具體表現為ViewPager的左右滑動不順暢,容易被SwipeRefreshLayout攔截(即出現重新整理的View).

問題原因:
ViewPager本身是處理了滾動事件的衝突,它在橫向滑動時會調用requestDisallowInterceptTouchEvent()方法使父控制項不攔截當前的Touch事件序列.但是SwipeRefreshLayout的requestDisallowInterceptTouchEvent()方法什麼也沒有做,所以仍然會攔截當前的Touch事件序列.

問題分析:
為什麼SwipeRefreshLayout的requestDisallowInterceptTouchEvent()方法什麼都不做?

首先SwipeRefreshLayout繼承自ViewGroup.

在requestDisallowInterceptTouchEvent()方法什麼都不做的情況下,使用者可以從底部下拉重新整理一次拉出LoadingView.
如果方法調用ViewGroup的requestDisallowInterceptTouchEvent()方法, 可以解決ViewPager的相容問題,但是使用者在介面底部下拉至頭部後,無法繼續下拉,需要手指放開一次才能拉出LoadingView.
目標分析:
那麼為了更加順滑地滾動,想要的效果當然是一次性拉出LoadingView.既然ViewPager在左右滑動時才會調用requestDisallowInterceptTouchEvent()方法,那麼SwipeRefreshLayout只應該在上下滑動時才攔截Touch事件.

具體邏輯如下:

記錄是否調用了requestDisallowInterceptTouchEvent()方法,並且設定為true.
在SwipeRefreshLayout中判斷是否是上下滑動.
如果同時滿足1,2,則調用super.requestDisallowInterceptTouchEvent(true).
否則調用super.requestDisallowInterceptTouchEvent(false).
注意:因為ViewGroup的requestDisallowInterceptTouchEvent方法設定true後,Touch事件在dispatchTouchEvent()方法中就會被攔截,所以需要在dispatchTouchEvent()方法中判斷是否為上下滑動.

實現代碼(部分):

//非法按鍵private static final int INVALID_POINTER = -1;//dispatch方法記錄第一次按下的xprivate float mInitialDisPatchDownX;//dispatch方法記錄第一次按下的yprivate float mInitialDisPatchDownY;//dispatch方法記錄的手指private int mActiveDispatchPointerId = INVALID_POINTER;//是否請求攔截private boolean hasRequestDisallowIntercept = false;@Overridepublic void requestDisallowInterceptTouchEvent(boolean b) {  hasRequestDisallowIntercept = b;  // Nope.}@Overridepublic boolean dispatchTouchEvent(MotionEvent ev) {  switch (ev.getAction()) {    case MotionEvent.ACTION_DOWN:      mActiveDispatchPointerId = MotionEventCompat.getPointerId(ev, 0);      final float initialDownX = getMotionEventX(ev, mActiveDispatchPointerId);      if (initialDownX != INVALID_POINTER) {        mInitialDisPatchDownX = initialDownX;      }      final float initialDownY = getMotionEventY(ev, mActiveDispatchPointerId);      if (mInitialDisPatchDownY != INVALID_POINTER) {        mInitialDisPatchDownY = initialDownY;      }      break;    case MotionEvent.ACTION_MOVE:      if (hasRequestDisallowIntercept) {        //解決viewPager滑動衝突問題        final float x = getMotionEventX(ev, mActiveDispatchPointerId);        final float y = getMotionEventY(ev, mActiveDispatchPointerId);        if (mInitialDisPatchDownX != INVALID_POINTER && x != INVALID_POINTER &&            mInitialDisPatchDownY != INVALID_POINTER && y != INVALID_POINTER) {          final float xDiff = Math.abs(x - mInitialDisPatchDownX);          final float yDiff = Math.abs(y - mInitialDisPatchDownY);          if (xDiff > mTouchSlop && xDiff * 0.7f > yDiff) {            //橫向滾動不需要攔截            super.requestDisallowInterceptTouchEvent(true);          } else {            super.requestDisallowInterceptTouchEvent(false);          }        } else {          super.requestDisallowInterceptTouchEvent(false);        }      }      break;    case MotionEvent.ACTION_UP:    case MotionEvent.ACTION_CANCEL:      if (ev.getAction() == MotionEvent.ACTION_UP || ev.getAction() == MotionEvent.ACTION_CANCEL) {        hasRequestDisallowIntercept = false;      }      break;  }  return super.dispatchTouchEvent(ev);}private float getMotionEventY(MotionEvent ev, int activePointerId) {  final int index = MotionEventCompat.findPointerIndex(ev, activePointerId);  if (index < 0) {    return -1;  }  return MotionEventCompat.getY(ev, index);}private float getMotionEventX(MotionEvent ev, int activePointerId) {  final int index = MotionEventCompat.findPointerIndex(ev, activePointerId);  if (index < 0) {    return -1;  }  return MotionEventCompat.getX(ev, index);}

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.