OnClickListener and OnTouchListener collision issues

1.2k views Asked by At

Currently working on an app in which I implement a chat head to make a view on top. I use an image for floating icon for chat heads, it working fine. what problem I face is that, both onClick and onTouch event not working properly either one of them is working at a time. How to make both of them working?.

3

There are 3 answers

1
Ognian Gloushkov On BEST ANSWER

I'd suggest you use only the OnTouchListener and handling the click case there using something like:

    ImageButton floatingIcon = (ImageButton) findViewById(R.id.floatingIcon);
    gestureDetector = new GestureDetector(this, new YourGestureListener());
    floatingIcon.setOnTouchListener(new OnTouchListener() {
        @Override
        public boolean onTouch(View arg0, MotionEvent arg1) {
            if (gestureDetector.onTouchEvent(arg1)) {
                // A single tap has been made - treat it like a click and consume the event
                return true;
            } else {
                // The MotionEvent is not a click event, handle and decide if the event is consumed
            }
            return false;
        }
    });

    private class YourGestureListener extends SimpleOnGestureListener {
        @Override
        public boolean onSingleTapUp(MotionEvent event) {
            return true;
        }
    }
0
ziLk On

Don't forget to return false in onTouch callback.

Button button = (Button) findViewById(R.id.button);
        button.setOnTouchListener(new OnTouchListener() {

            public boolean onTouch(View v, MotionEvent event) {
                Log.d("test", "ontouch");
                return false;
            }
        });
        button.setOnClickListener(new OnClickListener() {

            public void onClick(View v) {
                Log.d("test", "onclick");
            }

        });

And Don't forget that click is a action performed when user press the button and release but Touch will be taken when user presses it.

output :

03-22 16:19:39.735: D/test(682): ontouch
03-22 16:19:39.735: D/test(682): ontouch
03-22 16:19:39.735: D/test(682): onclick
0
Manohar On

You have to create custom event listner , here is what i used to get both swipe and click event

OnSwipeTouchListner.java

import android.content.Context;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;

public class OnSwipeTouchListener implements OnTouchListener {

    private final GestureDetector gestureDetector;
    private static final int MAX_CLICK_DURATION = 1000;
    private static final int MAX_CLICK_DISTANCE = 15;
 static Context mcontext;
    private long pressStartTime;
    private float pressedX;
    private float pressedY;
    private boolean stayedWithinClickDistance;

    public  int getLocationx() {
        return Locationx;
    }

    public void setLocationx(int locationx) {
        Locationx = locationx;
    }

    public int Locationx;

    public int getLocationy() {
        return Locationy;
    }

    public void setLocationy(int locationy) {
        Locationy = locationy;
    }

    public int Locationy;

    @SuppressWarnings("static-access")
    public OnSwipeTouchListener(Context context) {
        gestureDetector = new GestureDetector(context, new GestureListener());
        this.mcontext=context;
    }

    public void onSwipeLeft() {
    }

    public void onSwipeRight() {
    }
public void newTouch(){


}
    public boolean onTouch(View v, MotionEvent event) {
          gestureDetector.onTouchEvent(event);

         if(event.getAction()== MotionEvent.ACTION_MOVE)
         {
              if (stayedWithinClickDistance && distance(pressedX, pressedY, event.getX(), event.getY()) > MAX_CLICK_DISTANCE) {
                  stayedWithinClickDistance = false;
              }
             return true;
         }

         else if (event.getAction()== MotionEvent.ACTION_DOWN) {
             pressStartTime = System.currentTimeMillis();                
             pressedX = event.getX();
             pressedY = event.getY();
             stayedWithinClickDistance = true;

             return v.onTouchEvent(event);
         }
         else if(event.getAction()== MotionEvent.ACTION_UP) {

             long pressDuration = System.currentTimeMillis() - pressStartTime;
             if (pressDuration < MAX_CLICK_DURATION && stayedWithinClickDistance) {
                newTouch();
             }
             setLocationx((int)event.getX());
             setLocationy((int)event.getY());
             return v.onTouchEvent(event);
         }
         else{
             return v.onTouchEvent(event);
         }

    }
    private static float distance(float x1, float y1, float x2, float y2) {
        float dx = x1 - x2;
        float dy = y1 - y2;
        float distanceInPx = (float) Math.sqrt(dx * dx + dy * dy);
        return pxToDp(distanceInPx);
    }

    private static float pxToDp(float px) {
        return px / mcontext.getResources().getDisplayMetrics().density;
    }


    private final class GestureListener extends SimpleOnGestureListener {

        private static final int SWIPE_DISTANCE_THRESHOLD = 100;
        private static final int SWIPE_VELOCITY_THRESHOLD = 100;

        @Override
        public boolean onDown(MotionEvent e) {
            return true;
        }

        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            float distanceX = e2.getX() - e1.getX();
            float distanceY = e2.getY() - e1.getY();
            if (Math.abs(distanceX) > Math.abs(distanceY) && Math.abs(distanceX) > SWIPE_DISTANCE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
                if (distanceX > 0)
                    onSwipeRight();
                else
                    onSwipeLeft();
                return true;
            }
            return false;
        }

    }

}

and in main activity

imageView.setOnTouchListener(new OnSwipeTouchListener(this) {
                            @Override
                            public void onSwipeLeft() {

                   // Whatever for swipe left action

                            }
                            @Override
                            public void onSwipeRight() {

                                //Do what ever for swipe right action

                            }
                            @Override
                            public void newTouch() {
                                //Do what ever for single click Action

                            }

                        });