【问题标题】:GestureDetector - Detect double click in GridView item's although returning false in onTouchEvent()GestureDetector - 检测 GridView 项目中的双击,尽管在 onTouchEvent() 中返回 false
【发布时间】:2016-08-23 17:39:02
【问题描述】:

我写了一个简单的ImageView 子类,我想用它来检测对GridView-items 的双击:

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 的滑动和一个多选选择模式与 long按下。

我怎样才能解决这个问题,让所有这三个功能一起工作?

更新:我能够通过调试日志追踪问题。如果初始 onTouchEvent-call (MotionEvent.ACTION_DOWN) 返回 false,则相关的后续事件不会传递到 ImageView。因此,GestureDetector 无法理解它,因为它需要给定手势的所有相关 MotionEvent。

【问题讨论】:

    标签: java android gridview double-click touchscreen


    【解决方案1】:

    在阅读了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;
                }
            }
        }
    
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-01
      • 1970-01-01
      • 2018-12-28
      • 2021-07-03
      • 1970-01-01
      • 2019-10-03
      相关资源
      最近更新 更多