我需要在自定义视图的ontouch方法中使用singletap触摸检测。我试着得到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值不相同。当我们用手指在屏幕上触摸时,我想我还需要给单峰图设置一些范围。有人能给我一些建议吗?
要检测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;
}
}
在手势检测器的构造函数中使用:
detector = new GestureDetector(this, new GestureTap());
并在onTouch监听器中添加以下代码
@Override
public boolean onTouchEvent(MotionEvent event) {
detector.onTouchEvent(event);
return true;
}
为了完整性,如果有其他人到达这里,请添加答案:
您可以将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);
}
});
我最近也遇到了同样的问题,最终不得不实现一个debounce来让它工作。这并不理想,但在我找到更好的东西之前,它是相当可靠的。
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;
}
};
}
为视图添加GestureDetector.SimpleOnGestureListener,并在其中使用方法onSingleTapConfirmed。
只有当Android操作系统确认对特定对象的触摸是单次点击,而不是双击时,才会调用此方法。
你可以在谷歌上搜索android的例子。
有一种更简单、直接的方法。使用MotionEvent.ACTION_DOWN&;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;
}
}
认为您不需要使用"equal"运算符。而不是使用近似值
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值。
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;
}
});