OnClickListener 和 OnTouchListener 冲突问题

OnClickListener and OnTouchListener collision issues

目前正在开发一个应用程序,我在其中实现了一个聊天头以在顶部显示视图。我使用图像作为聊天头的浮动图标,效果很好。我面临的问题是,onClick 和 onTouch 事件都不能正常工作,其中任何一个都同时工作。如何让它们都工作?

不要忘记在 onTouch 回调中 return false

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");
            }

        });

并且不要忘记 click 是用户按下按钮并释放时执行的操作,但 Touch 将在用户按下按钮时执行。

输出:

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

您必须创建自定义事件侦听器,这是我用来获取滑动和点击事件的方法

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

    }

}

和主要 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

                            }

                        });

我建议您只使用 OnTouchListener 并使用类似以下内容处理点击情况:

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