GestureDetector - 检测GridView项目中的双击,虽然在onTouchEvent()中返回false [英] GestureDetector - Detect double click in GridView item's although returning false in onTouchEvent()

查看:244
本文介绍了GestureDetector - 检测GridView项目中的双击,虽然在onTouchEvent()中返回false的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我写了一个简单的 ImageView 子类,用于检测 GridView -items上的双击:

  public class DoubleClickImageView扩展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);无法使用gestureDetector
//返回false;无法使用gestureDetector
返回true; //工作但打破应用程序的其余部分
}

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();
}
返回true;

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

@Override
public boolean onDown(MotionEvent event){
//根据文档要求返回true on onDown,但不会帮助
返回true;
}
}

}



GridView 由使用此类显示的图像组成。



问题在于双击检测仅在 onTouchEvent 返回 true 时有效,否则 gestureDetector 中返回 true 时,没有检测到任何点击事件。 > onTouchEvent ,它打破了我的应用程序的其余部分,因为我还有一个全局 onTouchListener 来检测整个 GridView 和一个长按选择模式。



我该如何解决这个问题,以使所有这三个功能一起工作? / p>

更新:我能够使用调试日志追查问题。事实证明,当最初的onTouchEvent调用( MotionEvent.ACTION_DOWN )返回false时,相关的后续事件不会传递给 ImageView 。因此,GestureDetector无法理解它,因为它需要给定手势的所有相关MotionEvent。



我仍然需要解决此问题的解决方法。仅仅因为我需要在 ImageView -subclass中使用 GestureDetector 而打破了整个长按上下文操作栏,

解决方案

在阅读 http://balpha.de/2013/07/android-development-这个解决方法包括手动将MotionEvent传递给GridView的图像。
因此,我扩展了DoubleClickImageView类和我的GridView的适配器类,如下所示:
$ b

  
$ b $ / **
*解决方法:获取传递给GridView图像的手势的所有触摸事件,
*尽管onTouchEvent回调必须返回false以防止破坏
* GridView功能的其余部分。 (这些是滑动手势和我们的情况下的上下文操作栏)
*请参阅http://stackoverflow.com/questions/39107566/detect-double-click-on-imageview-works-only-when-ontouchevent-返回真#
* http://stackoverflow.com/questions/39100565/gesturedetector-detect-doubleclick-on-gridview-items
*了解更多信息
* /
公共类DoubleClickImageView扩展ImageView {

私人TouchEventForwarder touchEventForwarder;
private ClickListener imageClickListener;
private GestureDetector gestureDetector;
$ b $ **
*这需要在父级GridView适配器的getView()方法中调用
** /
public void setListeners(ClickListener dest,TouchEventForwarder src ){
imageClickListener = dest;
touchEventForwarder = src;

$ b $ **
*父级GridView适配器必须维护这个类的一个实例
** /
public static class TouchEventForwarder {

私人DoubleClickImageView currentClickedImage;
$ b $ **
*需要在父GridView接收的每个触摸事件上调用
** /
public void forwardTouchEvent(MotionEvent event){
if(currentlyClickedImage!= null){
currentClickedImage.onForwardedTouchEvent(event);
}
}

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

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

private void onForwardedTouchEvent(MotionEvent event){
/ **仅使用转发事件进行手势检测
*以防止评估重复事件** /
gestureDetector.onTouchEvent(event);
}

@Override
public boolean onTouchEvent(MotionEvent event){
/ **使用系统侦听器在事件转发器中注册视图** /
if(touchEventForwarder!= null){
touchEventForwarder.setNewReceiver(this);
}
返回super.onTouchEvent(event); //总是false
}

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

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

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


I wrote a simple subclass of ImageView that I want to use to detect double clicks on 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;
    }
}

}

The GridView consists of Images that are displayed using this class.

The problem is that the double click detection works only when onTouchEvent returns true, otherwise the gestureDetector does not detect any click event.

However, when I return true in the onTouchEvent, it breaks the rest of my application, since I have also a global onTouchListener to detect swipes over the whole GridView and a multiple choice select mode with long press.

How can I solve this problem so that all of these three features work together?

Update: I was able to trace down the problem with debug logs. It turned out that when the initial onTouchEvent-call (MotionEvent.ACTION_DOWN) returns false, the related follow-up-events are not delivered to the ImageView. Therefore the GestureDetector can not make any sense of it, since it needs all related MotionEvents of a given gesture.

I still need a workaround for this issue. Breaking the whole long-press contextual action bar just because I need to use a GestureDetector in an ImageView-subclass is extremely bad.

解决方案

I was finally able to find a workaround after reading the touch handling section of http://balpha.de/2013/07/android-development-what-i-wish-i-had-known-earlier/.

The workaround consists of manually passing MotionEvent's to the images of the GridView. Therefore I extended the DoubleClickImageView class and my GridView's adapter class as follows:

 

    /**
     * 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;
            }
        }
    }

这篇关于GestureDetector - 检测GridView项目中的双击,虽然在onTouchEvent()中返回false的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆