Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom view with buttons implements OnGestureListener

I've been breaking my head for the last couple of hours, googled the hell out of google and none of the examples on StackOverflow or other places worked for me so here it goes...

I have a custom view, that extends LinearLayout and implements GestureDetector.OnGestureListener.

In my custom layout I have 3 Buttons, each has a click listener. What I want is to be able to Fling everywhere in the view to perform something but also to be able to click on the buttons.

My onFling function works great if I fling inside the view but not over one of the buttons. If I fling over one of the buttons, it perform a click in most cases or nothing in some.

Here's the relevant part of my code:

@Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
            float velocityY) {
        if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH) {
            return false;
        }
        // right to left swipe
        if (e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE
                && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
            viewFlipper.setInAnimation(slideLeftIn);
            viewFlipper.setOutAnimation(slideLeftOut);
            viewFlipper.showNext();
            return true;

        } else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE
                && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
            viewFlipper.setInAnimation(slideRightIn);
            viewFlipper.setOutAnimation(slideRightOut);
            viewFlipper.showPrevious();
            return true;
        }

        return false;
    }

    @Override
    public boolean onDown(MotionEvent e) {
        // TODO Auto-generated method stub
        return true;
    }

    @Override
    public void onLongPress(MotionEvent e) {
        // TODO Auto-generated method stub

    }

    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
            float distanceY) {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public void onShowPress(MotionEvent e) {
        // TODO Auto-generated method stub

    }

    @Override
    public boolean onSingleTapUp(MotionEvent e) {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (gestureDetector.onTouchEvent(event)) {
            return gestureDetector.onTouchEvent(event);
        }
        return false;
    }

tried any combination of return true; return false; I could think of... Would appreciate any help! :)

Thanks!

like image 695
Lior Iluz Avatar asked Jun 07 '12 15:06

Lior Iluz


2 Answers

Here's what solved it for me eventually... (only the modified code from my question). Not sure if it's the best solution but it works:

@Override
    public boolean onDown(MotionEvent e) {
        // TODO Auto-generated method stub
        return false;
    }

@Override
    public boolean onTouchEvent(MotionEvent e) {
        return gestureDetector.onTouchEvent(e);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent e) {
        return onTouchEvent(e);
    }

This will allow the fling gesture, even over the buttons and also allow simple click on the buttons BUT if you have another view with buttons behind this view, sometimes the clicks will pass backwards and perform onClick on buttons behind the view. The solution for this is to add "android:clickable="true" to the front view's root layout (LinearLayout, FrameLayout or whatever).

like image 150
Lior Iluz Avatar answered Sep 24 '22 06:09

Lior Iluz


Here's an answer that might be relevant to the situation you're describing https://stackoverflow.com/a/9182176/780700

like image 32
eladr Avatar answered Sep 24 '22 06:09

eladr