Mike76 Mike76 - 3 months ago 19
Java Question

GestureDetector detect DoubleClick on GridView items

Note: This specific problem is solved, but there are serious follow-up problems. Have a look at Detect double click on ImageView works only when onTouchEvent returns true

I want to detect double clicks on distinct items in a

GridView
of images.
Therefore I assigned a separate
OnTouchListener
to each item-
imageView
in the
getView()
method of the adapter. The
gestureDetector
is a member variable of the adapter-class.

private GestureDetectorCompat gestureDetector;

public ImageGridViewAdapter(Context c, ArrayList<UriWrapper> startUpImages) {
mContext = c;
uriManager = new UriManager(startUpImages);
gestureDetector = new GestureDetectorCompat(mContext, new SingleTapConfirm());
}

public View getView(final int position, View recycled, ViewGroup parent) {

ViewHolder holder;
if (recycled == null) {
..... find items by id
} else{
holder = (ViewHolder) recycled.getTag();
}

// Set listener to item image
holder.image.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
// Always returns false, the gestureDetector does not detect anything
boolean ret = gestureDetector.onTouchEvent(event);
// At least the onTouch-callback gets called with the correct position
Log.e(TAG, "onTouch returned " + ret + " at position " + position);
return true;
}
});

// Use glide library to load images into the image views
Glide.with(mContext)....into(holder.image);
return recycled;
}


private class SingleTapConfirm extends GestureDetector.SimpleOnGestureListener {

@Override
public boolean onSingleTapConfirmed(MotionEvent event) {
Log.e(TAG, "onSingleTapConfirmed"); // never called..
return true;
}

@Override
public boolean onDoubleTap(MotionEvent e) {
Log.e(TAG, "onDoubleTap"); // never called..
return super.onDoubleTap(e);
}
}


The
OnTouchListener
's work and get called with the correct position.
However, no matter what I am doing, the methods of the
GestureDetector
are never called. What seems to be the issue with this code?

Update: The onTouch-callback needs to return true, now at least the GestureDetector works. However, returning true breaks the rest of the functionality, since I have a long-click-selection-mode and a global OnTouchListener for my GridView.

Second Update:
Merging the item-specific OnTouchListener and the global OnTouchListener did not work properly. (swipe gestures only recognized on certain items)
I hope that I can work around these two problems by creating a custom View extending ImageView and assigning the item-specific OnTouchListener there.

Answer
 private GestureDetectorCompat gestureDetector;

    // in your adapter constructor
    gestureDetector = new GestureDetector(context, new SingleTapConfirm());

    public View getView(final int position, View recycled, ViewGroup parent) {

        ViewHolder holder;
        if (recycled == null) {
            .....find items by id
        } else {
            holder = (ViewHolder) recycled.getTag();
        }

        // Set listener to item image
        holder.image.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                // Use lazy initialization for the gestureDetector
                gestureDetector.onTouchEvent(event);
                // At least the onTouch-callback gets called with the correct position
                return true;
            }
        });

        // Use glide library to load images into the image views
        Glide.with(mContext)....into(holder.image);
        return recycled;
    }

    private class SingleTapConfirm extends GestureDetector.SimpleOnGestureListener {

        @Override
        public boolean onSingleTapConfirmed(MotionEvent event) {
            Log.e(TAG, "onSingleTapConfirmed"); // never called..
            return true;
        }

        @Override
        public boolean onDoubleTap(MotionEvent e) {
            Log.e(TAG, "onDoubleTap"); // never called..
            return super.onDoubleTap(e);
        }
    }

Update:

        @Override
        public boolean onTouch(View v, MotionEvent event) {anything
            gestureDetector.onTouchEvent(event);
            return true;
        }