1. 程式人生 > >解決ViewPager巢狀Fragment內部點選事件無響應問題

解決ViewPager巢狀Fragment內部點選事件無響應問題

之前一直在找關於ViewPager Fragment之間的問題,然後找了很久都不是很理想。感覺都快瘋了,後來找到在老大的指點下找到了一篇文章解決了這個問題,和老大相比找了很久我就絕望了對這個不抱有信心了,老大一開始也不知道,但是他在耐心的找問題,一個一個排除,一種一種方法試。最後偶然的情況下發現這篇文章,然後解決了問題。和老大相比還是沒有解決問題的耐心啊,廢話少說貼上文章



    

            圖1                圖2                        圖3

  onInterceptTouchEvent 和 onTouchEvent 清楚了,還有個 dispatchTouchEvent

 不太清楚,網上說是分發事件的,在除錯時,我發現 viewgroup 的分發機制似乎不同(dispatchTouchEvent在onInterceptTouchEvent後呼叫)。

  最終找到這篇文章 "Android事件處理第一節(View對Touch事件的處理)",看到其中 View.dispatchTouchEvent() 的原始碼,又是豁然開朗.

複製程式碼
    public boolean dispatchTouchEvent(MotionEvent event) 
    {  
        if (mInputEventConsistencyVerifier != null
) { mInputEventConsistencyVerifier.onTouchEvent(event, 0); } if (onFilterTouchEventForSecurity(event)) { //noinspection SimplifiableIfStatement ListenerInfo li = mListenerInfo; if (li != null && li.mOnTouchListener != null
&& (mViewFlags & ENABLED_MASK) == ENABLED && li.mOnTouchListener.onTouch(this, event)) { return true; } if (onTouchEvent(event)) { return true; } } if (mInputEventConsistencyVerifier != null) { mInputEventConsistencyVerifier.onUnhandledEvent(event, 0); } return false; }
複製程式碼

  也就是說是 dispatchTouchEvent 在呼叫 onTouchEvent 。

  思路:

      最終效果是豎直方向滑動時listview動起來,水平方向滑動viewpager動起來,顯然我需要對滑動手勢進行判斷,

     (1)  在 case MotionEvent.ACTION_DOWN: 分支獲取第一次按下點的座標
    
     (2)  在 case MotionEvent.ACTION_MOVE: 分支獲取移動結束點的座標

     (3)  通過兩點橫座標差值與豎座標的差值可以判斷手勢方向;

      這裡我的view層次是,activity->viewpager->listview.

      所以我希望它的事件流向像下圖一樣

      

      思路差不多就這些.

   解決:

      直接上程式碼吧.

複製程式碼
/*  程式碼位置:複寫ViewPager的onTouchEvent方法*/

private float xDistance, yDistance, xLast, yLast; /* (non-Javadoc) * @see android.widget.AbsListView#onTouchEvent(android.view.MotionEvent) */ @Override public boolean onTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: //獲取第一次按下點的座標 xDistance = yDistance = 0f; xLast = ev.getX(); yLast = ev.getY(); break; case MotionEvent.ACTION_MOVE:        //獲取移動結束點的座標  final float curX = ev.getX(); final float curY = ev.getY();
       //差值 xDistance
+= Math.abs(curX - xLast); yDistance += Math.abs(curY - yLast); xLast = curX; yLast = curY; if(xDistance <= yDistance) return super.onTouchEvent(ev); // 消耗 else return false; // 往下傳遞 } return super.onTouchEvent(ev); }
複製程式碼

      如果你的專案,viewpager之下還有 view ,並且還有手勢處理,那你可以對你想遮蔽的 view 使用 requestDisallowInterceptTouchEvent(true); ,比如說我這的Activity還有手勢處理,我想遮蔽它,於是就在 viewpager 的 onInterceptTouchEvent 裡呼叫了 getParent().requestDisallowInterceptTouchEvent(true); ,程式碼如下

  @Override
    public boolean onInterceptTouchEvent(MotionEvent arg0) 
    {
        getParent().requestDisallowInterceptTouchEvent(true);
        return super.onInterceptTouchEvent(arg0);
    }
原地址 http://m.blog.csdn.net/blog/u012124604/38757145