2016-08-23 7 views
0

Я написал простой подкласс ImageView, что я хочу использовать для обнаружения двойных щелчков на GridView -Детали:GestureDetector - Обнаружение двойного щелчка в GridView элемента, в хотя возвращении ложного в onTouchEvent()

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 не обнаруживает никаких событий щелчка.

Однако, когда я вернусь true в onTouchEvent, он ломает остальную часть моего приложения, так как у меня также глобальный onTouchListener обнаружить пойло по всему GridView и выбору выбора режима множественного с длинным нажатием.

Как я могу решить эту проблему, чтобы все эти три функции работали вместе?

Обновление: Я смог проследить проблему с журналами отладки. Оказалось, что когда начальный вызов onTouchEvent (MotionEvent.ACTION_DOWN) возвращает false, соответствующие события последующего события не доставляются в ImageView. Поэтому GestureDetector не может этого толковать, так как ему нужны все связанные MotionEvents данного жестов.

Мне все еще нужно обходное решение для этой проблемы. Прерывая весь контекстный контекстный экран действия только потому, что мне нужно использовать GestureDetector в ImageView -subclass очень плохо.

ответ

0

Наконец-то я смог найти обходное решение после прочтения раздела обработки касания http://balpha.de/2013/07/android-development-what-i-wish-i-had-known-earlier/.

Обходной путь состоит в том, чтобы вручную передать MotionEvent's изображениям 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; 
      } 
     } 
    } 

 Смежные вопросы

  • Нет связанных вопросов^_^