2010-09-30 22 views
4

我有一個ListView裏面的ViewFlipper,當用戶在屏幕上滑動時,我正在翻頁。點擊一個ListView將打開瀏覽器。有時當我滑動時,它會作爲ListView上的觸摸被檢測到,並會打開瀏覽器。這可能很煩人。我怎樣才能防止這種情況發生?如何區分一觸即發?

class MyGestureDetector extends SimpleOnGestureListener { 
     @Override 
     public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { 
      try { 
       if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH) 
        return false; 
       // right to left swipe 
       if (e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) { 
        viewFlipper.setInAnimation(slideLeftIn); 
        viewFlipper.setOutAnimation(slideLeftOut); 
        viewFlipper.showNext(); 
       } else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) { 
        viewFlipper.setInAnimation(slideRightIn); 
        viewFlipper.setOutAnimation(slideRightOut); 
        viewFlipper.showPrevious(); 
       } 

       if (viewFlipper.getDisplayedChild() == 0) { 
        // TODO: light up left 
        flipperPosition = 0; 
       } else if (viewFlipper.getDisplayedChild() == 1) { 
        // TODO: light up middle 
        flipperPosition = 1; 
       } else if (viewFlipper.getDisplayedChild() == 2) { 
        // TODO: light up right 
        flipperPosition = 2; 
       } 
      } catch (Exception e) { 
       System.out.println(e); 
      } 
      return false; 
     } 
    } 

protected MotionEvent downStart = null; 

     public boolean onInterceptTouchEvent(MotionEvent event) { 

      switch(event.getAction()) { 
      case MotionEvent.ACTION_DOWN: 
       // keep track of the starting down-event 
       downStart = MotionEvent.obtain(event); 
       break; 
      case MotionEvent.ACTION_MOVE: 
       // if moved horizontally more than slop*2, capture the event for ourselves 
       float deltaX = event.getX() - downStart.getX(); 
       if(Math.abs(deltaX) > ViewConfiguration.getTouchSlop() * 2) 
        return true; 
       break; 
      } 

      // otherwise let the event slip through to children 
      return false; 
     } 
+10

觸摸持續一會兒。投擲可能會持續幾天。通常情況下,投擲是由許多觸摸... – FrustratedWithFormsDesigner 2010-09-30 18:56:31

+2

完全無關的問題,但我LOL'd,FrustratedWithFormsDesigner。 :^) – mahdaeng 2012-02-05 03:25:17

回答

12

通常這樣做的方式是通過父視圖的onInterceptTouchEvent方法。 onInterceptTouchEvent有機會在觀看孩子之前看到任何觸摸事件。如果onInterceptTouchEvent返回true,先前處理觸摸事件的子視圖會收到ACTION_CANCEL,並將來自該點的事件發送到父級的onTouchEvent方法以進行常規處理。它還可以返回false,並簡單地監視事件,因爲它們沿着視圖層次結構傳播到其通常的目標。

你想基本上這onInterceptTouchEvent請在你檢測甩父視圖:

  • ACTION_DOWN,記錄觸摸的位置。返回false
  • ACTION_MOVE上,檢查初始觸地位置與當前位置之間的增量。如果它超過閾值(框架使用ViewConfiguration#getScaledTouchSlop()ViewConfiguration的其他適當值作爲此類事情),則返回true
  • 像往常一樣根據onTouchEvent檢測並處理一排。

一旦你截獲,ListView將取消其觸摸處理,你不會在你的列表項上得到不需要的輕擊事件。 ListView也被設置爲在用戶開始垂直滾動列表時不允許其父母攔截事件,這意味着如果用戶縱向晃動列表,則不會發生錯誤的水平甩動。

這就是股票Android啓動器或新聞和天氣如何對滾動/可點擊內容進行並排分頁。

+0

我試着實施onInterceptTouchEvent,但該方法永遠不會被調用。查看我的更新代碼 – 2010-09-30 22:47:34

+0

onInterceptTouchEvent是一個重寫的View方法,而不是偵聽器方法。 – adamp 2010-09-30 22:49:03

+0

我不太清楚你的意思?你能告訴我一個示例用法嗎? – 2010-10-01 00:51:39

1

您是否嘗試過使用SimpleOnGestureListener.onSingleTapConfirmed(MotionEvent)的觸摸事件( 「點擊」)?這隻會在檢測器確信用戶的第一次敲擊實際上是敲擊而不是雙擊(或者希望是一拍子)之後才被調用。

class MyGestureDetector extends SimpleOnGestureListener { 
    @Override 
    public boolean onSingleTapConfirmed(MotionEvent event) { 
     // Code... 
    } 
} 
+0

我沒有,但我不知道我怎麼可以掛鉤我的ListView到這個? – 2010-09-30 20:30:34