2016-08-23 63 views
0

我寫的ImageView一個簡單的子類,我想用它來檢測上GridView -items雙擊:GestureDetector - 檢測在GridView控件項目的雙擊儘管在的onTouchEvent()返回false

public class DoubleClickImageView extends ImageView { 

public interface ClickListener { 
    void onSingleClick(); 
    void onDoubleClick(); 
} 

private ClickListener imageClickReceiver; 
private GestureDetector gestureDetector; 

@Override 
public boolean onTouchEvent(MotionEvent event) { 
    gestureDetector.onTouchEvent(event); 
    // return super.onTouchEvent(event); does not work with gestureDetector 
    // return false; does not work with gestureDetector 
    return true; // works but breaks the rest of the application 
} 

public void setDoubleClickListener(ClickListener listener) { 
    imageClickReceiver = listener; 
} 

public DoubleClickImageView(Context cx, AttributeSet attrs) { 
    super(cx, attrs); 
    gestureDetector = new GestureDetector(cx, new InternalClickListener()); 
} 

private class InternalClickListener extends GestureDetector.SimpleOnGestureListener { 

    @Override 
    public boolean onSingleTapConfirmed(MotionEvent event) { 
     if (imageClickReceiver != null) { 
      imageClickReceiver.onSingleClick(); 
     } 
     return true; 
    } 

    @Override 
    public boolean onDoubleTap(MotionEvent e) { 
     if (imageClickReceiver != null) { 
      imageClickReceiver.onDoubleClick(); 
     } 
     return true; 
    } 

    @Override 
    public boolean onDown(MotionEvent event) { 
     //return true for onDown is required according to docs but does not help 
     return true; 
    } 
} 

}

GridView由使用此類顯示的圖像組成。

問題是雙擊檢測僅在onTouchEvent返回true時有效,否則gestureDetector不會檢測到任何點擊事件。

然而,當我在onTouchEvent返回true,它打破了我的應用程序的其餘部分,因爲我也有一個全球性的onTouchListener在整個GridView和多選擇選擇模式與長按檢測刷卡。

我該如何解決這個問題,使所有這三個功能一起工作?

更新:我能夠跟蹤調試日誌的問題。事實證明,當初始的onTouchEvent-調用(MotionEvent.ACTION_DOWN)返回false時,相關的後續事件不會傳遞到ImageView。因此,手勢檢測器無法理解它,因爲它需要給定手勢的所有相關MotionEvent。

我仍然需要解決此問題的解決方法。打破整個長按上下文操作欄,只是因爲我需要在ImageView子類中使用GestureDetector非常糟糕。

回答

0

在閱讀http://balpha.de/2013/07/android-development-what-i-wish-i-had-known-earlier/的觸控操作部分後,我終於找到了解決方法。

解決方法包括手動將MotionEvent傳遞給GridView的圖像。 因此,我擴展了DoubleClickImageView類和我的GridView的適配器類,如下所示:



    /** 
    * A workaround to get all touch events of a gesture delivered to GridView-images, 
    * although the onTouchEvent-callback has to return false to prevent breaking the 
    * rest of the GridView-functionality. (these are swipe gestures and a contextual action bar in our case) 
    * See http://stackoverflow.com/questions/39107566/detect-double-click-on-imageview-works-only-when-ontouchevent-returns-true# 
    * http://stackoverflow.com/questions/39100565/gesturedetector-detect-doubleclick-on-gridview-items 
    * for more information 
    */ 
    public class DoubleClickImageView extends ImageView { 

     private TouchEventForwarder touchEventForwarder; 
     private ClickListener imageClickListener; 
     private GestureDetector gestureDetector; 

     /** 
     * This needs to be called in the parent GridView adapter's getView() method 
     **/ 
     public void setListeners(ClickListener dest, TouchEventForwarder src) { 
      imageClickListener = dest; 
      touchEventForwarder = src; 
     } 

     /** 
     * The parent GridView adapter has to maintain an instance of this class 
     **/ 
     public static class TouchEventForwarder { 

      private DoubleClickImageView currentlyClickedImage; 

      /** 
      * This needs to be called on each touch event received by the parent GridView 
      **/ 
      public void forwardTouchEvent(MotionEvent event) { 
       if (currentlyClickedImage != null) { 
        currentlyClickedImage.onForwardedTouchEvent(event); 
       } 
      } 

      private void setNewReceiver(DoubleClickImageView doubleClickImageView) { 
       currentlyClickedImage = doubleClickImageView; 
      } 
     } 

     public interface ClickListener { 
      void onSingleClick(); 
      void onDoubleClick(); 
     } 

     private void onForwardedTouchEvent(MotionEvent event) { 
      /** Use only forwarded events for gesture detection 
      * to prevent the evaluation of duplicate events **/ 
      gestureDetector.onTouchEvent(event); 
     } 

     @Override 
     public boolean onTouchEvent(MotionEvent event) { 
      /** Use the system listener to register the view at the event forwarder**/ 
      if (touchEventForwarder != null) { 
       touchEventForwarder.setNewReceiver(this); 
      } 
      return super.onTouchEvent(event); // always false 
     } 

     public DoubleClickImageView(Context cx, AttributeSet attrs) { 
      super(cx, attrs); 
      gestureDetector = new GestureDetector(cx, new InternalClickListener()); 
     } 

     private class InternalClickListener extends GestureDetector.SimpleOnGestureListener { 
      @Override 
      public boolean onSingleTapConfirmed(MotionEvent event) { 
       if (imageClickListener != null) { 
        imageClickListener.onSingleClick(); 
       } 
       return true; 
      } 

      @Override 
      public boolean onDoubleTap(MotionEvent event) { 
       if (imageClickListener != null) { 
        imageClickListener.onDoubleClick(); 
       } 
       return true; 
      } 
     } 
    } 

相關問題