我需要在自定义视图的ontouch方法中进行单点触控检测。我尝试在ACTION-DOWN和ACTION-UP中获取x和y值,在ACTION-UP中我给出了一个条件,即如果ACTIONDOWN和ACTION-UP中的X和Y的值相等,则将其作为单击
我的代码如下
@Override
public boolean onTouchEvent(MotionEvent ev) {
if (!mSupportsZoom && !mSupportsPan) return false;
mScaleDetector.onTouchEvent(ev);
final int action = ev.getAction();
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN: {
final float x = ev.getX();
final float y = ev.getY();
mLastTouchX = x; //here i get x and y values in action down
mLastTouchY = y;
mActivePointerId = ev.getPointerId(0);
break;
}
case MotionEvent.ACTION_MOVE: {
final int pointerIndex = ev.findPointerIndex(mActivePointerId);
final float x = ev.getX(pointerIndex);
final float y = ev.getY(pointerIndex);
if (mSupportsPan && !mScaleDetector.isInProgress()) {
final float dx = x - mLastTouchX;
final float dy = y - mLastTouchY;
mPosX += dx;
mPosY += dy;
//mFocusX = mPosX;
//mFocusY = mPosY;
invalidate();
}
mLastTouchX = x;
mLastTouchY = y;
break;
}
case MotionEvent.ACTION_UP: {
final float x = ev.getX();
final float y = ev.getY();
touchupX=x; //here is get x and y values at action up
touchupY=y;
if(mLastTouchX == touchupX && mLastTouchY == touchupY){ //my condition if both the x and y values are same .
PinchZoomPanActivity2.tapped1(this.getContext(), 100); //my method if the singletap is detected
}
else{
}
mActivePointerId = INVALID_POINTER_ID;
break;
}
case MotionEvent.ACTION_CANCEL: {
mActivePointerId = INVALID_POINTER_ID;
break;
}
case MotionEvent.ACTION_POINTER_UP: {
final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK)
>> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
final int pointerId = ev.getPointerId(pointerIndex);
if (pointerId == mActivePointerId) {
final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
mLastTouchX = ev.getX(newPointerIndex);
mLastTouchY = ev.getY(newPointerIndex);
mActivePointerId = ev.getPointerId(newPointerIndex);
}
break;
}
}
return true;
}
但我无法完成它。我的意思是在我的方法的每个动作都被调用。即使actionup和actiondown的x和y值不相同。当我们用手指在屏幕上触摸时,我想我还需要为单声道放置一些范围。有谁能建议我一些方法?
答案 0 :(得分:37)
要在android中检测单击和双击我使用以下方法:
class GestureTap extends GestureDetector.SimpleOnGestureListener {
@Override
public boolean onDoubleTap(MotionEvent e) {
Log.i("onDoubleTap :", "" + e.getAction());
return true;
}
@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
Log.i("onSingleTap :", "" + e.getAction());
return true;
}
}
在GestureDetector的构造函数中使用它:
detector = new GestureDetector(this, new GestureTap());
在onTouch侦听器中添加以下代码
@Override
public boolean onTouchEvent(MotionEvent event) {
detector.onTouchEvent(event);
return true;
}
答案 1 :(得分:11)
为了完整性而添加答案,如果有其他人到达此处:
您可以GestureDetector
使用OnTouchListener
final GestureDetector gestureDetector = new GestureDetector(this, new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
//do something
return true;
}
@Override
public void onLongPress(MotionEvent e) {
super.onLongPress(e);
}
@Override
public boolean onDoubleTap(MotionEvent e) {
return super.onDoubleTap(e);
}
});
viewToTouch.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return gestureDetector.onTouchEvent(event);
}
});
答案 2 :(得分:8)
我最近也遇到了同样的问题,并最终不得不实施去抖动以使其正常工作。它并不理想,但在我找到更好的东西之前它是非常可靠的。
View.onClickListener对我来说更可靠,但不幸的是我需要来自OnTouchListener的MotionEvent。
编辑:删除了导致其失败的多余代码
class CustomView extends View {
private static long mDeBounce = 0;
static OnTouchListener listenerMotionEvent = new OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if ( Math.abs(mDeBounce - motionEvent.getEventTime()) < 250) {
//Ignore if it's been less then 250ms since
//the item was last clicked
return true;
}
int intCurrentY = Math.round(motionEvent.getY());
int intCurrentX = Math.round(motionEvent.getX());
int intStartY = motionEvent.getHistorySize() > 0 ? Math.round(motionEvent.getHistoricalY(0)) : intCurrentY;
int intStartX = motionEvent.getHistorySize() > 0 ? Math.round(motionEvent.getHistoricalX(0)) : intCurrentX;
if ( (motionEvent.getAction() == MotionEvent.ACTION_UP) && (Math.abs(intCurrentX - intStartX) < 3) && (Math.abs(intCurrentY - intStartY) < 3) ) {
if ( mDeBounce > motionEvent.getDownTime() ) {
//Still got occasional duplicates without this
return true;
}
//Handle the click
mDeBounce = motionEvent.getEventTime();
return true;
}
return false;
}
};
}
答案 3 :(得分:4)
为视图添加 GestureDetector.SimpleOnGestureListener ,并在此处使用方法 onSingleTapConfirmed 。
只有在Android操作系统确认触摸特定是单击并且不是双击时才会调用此方法。
你可以google for android examples。
答案 4 :(得分:4)
有一种更简单直接的方式。 使用MotionEvent.ACTION_DOWN&amp;&amp; MotionEvent.ACTION_UP并计算事件之间的差异。
完整的代码可以在这里找到。 https://stackoverflow.com/a/15799372/3659481
setOnTouchListener(new OnTouchListener() {
private static final int MAX_CLICK_DURATION = 200;
private long startClickTime;
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
startClickTime = Calendar.getInstance().getTimeInMillis();
break;
}
case MotionEvent.ACTION_UP: {
long clickDuration = Calendar.getInstance().getTimeInMillis() - startClickTime;
if(clickDuration < MAX_CLICK_DURATION) {
//click event has occurred
}
}
}
return true;
}
}
答案 5 :(得分:0)
认为您不需要使用“相等”运算符。而不是使用近似值
case MotionEvent.ACTION_DOWN: {
final int CONST = 5;
final float x = ev.getX();
final float y = ev.getY();
mLastTouchXMax = x+CONST; //here i get x and y values in action down
mLastTouchXMin = x-CONST;
mLastTouchYMax = y+CONST;
mLastTouchYMin = y-CONST;
mActivePointerId = ev.getPointerId(0);
break;
}
并在ACTION_UP中检查间隔之间的X和Y值。
答案 6 :(得分:0)
float dX,dY,x,y;
tv.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_UP: //Event for On Click
if(x==view.getX() && y==view.getY()){
Toast.makeText(getApplicationContext(),"TextView Clicked",Toast.LENGTH_LONG).show();
}
break;
case MotionEvent.ACTION_DOWN:
x=view.getX();
y=view.getY();
dX = view.getX() - event.getRawX();
dY = view.getY() - event.getRawY();
break;
case MotionEvent.ACTION_MOVE:
view.animate()
.x(event.getRawX() + dX)
.y(event.getRawY() + dY)
.setDuration(0)
.start();
break;
default:
return false;
}
return true;
}
});