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;
}
}
目前正在开发一个应用程序,我在其中实现了一个聊天头以在顶部显示视图。我使用图像作为聊天头的浮动图标,效果很好。我面临的问题是,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;
}
}