Android中的DoubleTap

我需要创build一个小文本区域。在文本区域,当我双击,它将移动到下一个activity.How我可以做到这一点?

Solutions Collecting From Web of "Android中的DoubleTap"

如果你做的设置正确,在GestureListenerOnDoubleTapListener是非常有用的。 你不需要处理每一个水龙头,并计算两者之间的时间。 相反,让Android为您处理什么是水龙头,双击,滚动或一扔。 使用实现GestureListenerOnDoubleTapListener的帮助程序类SimpleGestureListener ,您不需要太多操作。

 findViewById(R.id.touchableText).setOnTouchListener(new OnTouchListener() { private GestureDetector gestureDetector = new GestureDetector(Test.this, new GestureDetector.SimpleOnGestureListener() { @Override public boolean onDoubleTap(MotionEvent e) { Log.d("TEST", "onDoubleTap"); return super.onDoubleTap(e); } ... // implement here other callback methods like onFling, onScroll as necessary }); @Override public boolean onTouch(View v, MotionEvent event) { Log.d("TEST", "Raw event: " + event.getAction() + ", (" + event.getRawX() + ", " + event.getRawY() + ")"); gestureDetector.onTouchEvent(event); return true; } }); 

注意:我testing了好一阵子才知道, return truereturn false的正确组合是什么。 这是这里非常棘手的部分。

另一个注意事项:当你testing这个, 在真实的设备上 ,而不是模拟器。 我真的很难让鼠标快速创build一个onFling事件。 真正的设备上真正的手指似乎要快得多。

更好的select是创build一个轻量级的抽象类

 public abstract class DoubleClickListener implements OnClickListener { private static final long DOUBLE_CLICK_TIME_DELTA = 300;//milliseconds long lastClickTime = 0; @Override public void onClick(View v) { long clickTime = System.currentTimeMillis(); if (clickTime - lastClickTime < DOUBLE_CLICK_TIME_DELTA){ onDoubleClick(v); lastClickTime = 0; } else { onSingleClick(v); } lastClickTime = clickTime; } public abstract void onSingleClick(View v); public abstract void onDoubleClick(View v); } 

并使用它

  view.setOnClickListener(new DoubleClickListener() { @Override public void onSingleClick(View v) { } @Override public void onDoubleClick(View v) { } }); 

很简单的逻辑使用下面的代码

  boolean firstTouch = false; @Override public boolean onTouchEvent(MotionEvent event) { if(event.getAction() == event.ACTION_DOWN){ if(firstTouch && (Helper.getCurrentTimeInMilliSeconds() - time) <= 300) { //do stuff here for double tap Log.e("** DOUBLE TAP**"," second tap "); firstTouch = false; } else { firstTouch = true; time = Helper.getCurrentTimeInMilliSeconds(); Log.e("** SINGLE TAP**"," First Tap time "+time); return false; } } return true; } 

———-

我采取了不同的方法来实现Android视图的双击。 我创build了自己的逻辑来检测双击,这很容易实现。

以下是执行此操作的步骤:
1.在要接收触摸事件的视图上设置onTouchListener。
2.实现onTouch(视图,事件)方法。 (在双击中,键是检测两个ACTION_DOWN和ACTION_UP事件,为此我们必须计算两个连续的下行事件之间的持续时间)。

这是达到这个目的的逻辑:

  /* variable for counting two successive up-down events */ int clickCount = 0; /*variable for storing the time of first click*/ long startTime; /* variable for calculating the total time*/ long duration; /* constant for defining the time duration between the click that can be considered as double-tap */ static final MAX_DURATION = 500; @Override public boolean onTouch (View v, MotionEvent event) { switch(event.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: startTime = System.currentTimeMillis(); clickCount++; break; case MotionEvent.ACTION_UP: long time = System.currentTimeMillis() - startTime; duration= duration + time; if(clickCount == 2) { if(totalTime <= DURATION) { Toast.makeText(captureActivity.this, "double tap",Toast.LENGTH_LONG).show(); } clickCount = 0; duration = 0; break; } } return true; } 

====编辑======

对于我来说,以上是不能接受的改变build议的变化 – 超时不适用于上述逻辑。

用这个来代替

@Override public boolean onTouch(View paramView,MotionEvent event){switch(event.getAction()&MotionEvent.ACTION_MASK){

  case MotionEvent.ACTION_UP: clickCount++; if (clickCount==1){ startTime = System.currentTimeMillis(); } else if(clickCount == 2) { long duration = System.currentTimeMillis() - startTime; if(duration <= ONE_SECOND) { Toast.makeText(captureActivity.this, "double tap",Toast.LENGTH_LONG).show(); clickCount = 0; duration = 0; }else{ clickCount = 1; startTime = System.currentTimeMillis(); } break; } } return true; 

}

 import android.app.Activity; import android.view.GestureDetector; import android.view.MotionEvent; import android.view.GestureDetector.SimpleOnGestureListener; import android.widget.Toast; public class SimpleGestureFilter extends SimpleOnGestureListener { public final static int SWIPE_UP = 1; public final static int SWIPE_DOWN = 2; public final static int SWIPE_LEFT = 3; public final static int SWIPE_RIGHT = 4; public final static int MODE_TRANSPARENT = 0; public final static int MODE_SOLID = 1; public final static int MODE_DYNAMIC = 2; private final static int ACTION_FAKE = -13; private int swipe_Min_Distance = 100; private int swipe_Max_Distance = 350; private int swipe_Min_Velocity = 100; private int mode = MODE_DYNAMIC; private boolean running = true; private boolean tapIndicator = false; private Activity context; private GestureDetector detector; private SimpleGestureListener listener; public SimpleGestureFilter(Activity context,SimpleGestureListener sgf) { this.context = context; this.detector = new GestureDetector(context, this); this.listener = sgf; } public void onTouchEvent(MotionEvent me) { // TODO Auto-generated method stub if(!this.running) return; boolean result=this.detector.onTouchEvent(me); if(this.mode==MODE_SOLID) me.setAction(MotionEvent.ACTION_CANCEL); else if(this.mode==MODE_DYNAMIC) { if(me.getAction()==ACTION_FAKE) me.setAction(MotionEvent.ACTION_UP); else if(result) me.setAction(MotionEvent.ACTION_CANCEL); else if(this.tapIndicator) { me.setAction(MotionEvent.ACTION_DOWN); this.tapIndicator=false; } } } public void setMode(int m) { this.mode=m; } public int getMode() { return this.mode; } public void setEnabled(boolean status) { this.running=status; } public void setSwipeMaxDistance(int distance) { this.swipe_Max_Distance=distance; } public void setSwipeMinDistance(int distance) { this.swipe_Min_Distance=distance; } public int getSwipeMaxDistance() { return this.swipe_Max_Distance; } public int getSwipeMinDistance() { return this.swipe_Min_Distance; } public int getSwipeMinVelocity() { return this.swipe_Min_Velocity; } public boolean onFling(MotionEvent e1,MotionEvent e2,float velocityX,float velocityY) { final float xDistance=Math.abs(e1.getX()-e2.getX()); final float yDistance=Math.abs(e1.getY()-e2.getY()); if(xDistance>this.swipe_Max_Distance || yDistance> this.swipe_Max_Distance) return false; velocityX = Math.abs(velocityX); velocityY = Math.abs(velocityY); boolean result=false; if(velocityX > this.swipe_Min_Velocity && xDistance > this.swipe_Min_Distance) { if(e1.getX() > e2.getX()) // right to left Move this.listener.onSwipe(SWIPE_LEFT); else this.listener.onSwipe(SWIPE_RIGHT); result=true; } else if(velocityY > this.swipe_Min_Velocity && yDistance > this.swipe_Min_Distance) { if(e1.getY() > e2.getY()) // bottom to top Move this.listener.onSwipe(SWIPE_UP); else this.listener.onSwipe(SWIPE_DOWN); result=true; } return result; } public boolean onSingleTapUp(MotionEvent e) { this.tapIndicator=true; return false; } public boolean onDoubleTap(MotionEvent e) { this.listener.onDoubleTap(); return false; } public boolean onDoubleTapEvent(MotionEvent e) { return true; } public boolean onSingleTapConfirmed(MotionEvent e) { if(this.mode==MODE_DYNAMIC) { e.setAction(ACTION_FAKE); this.context.dispatchTouchEvent(e); } return false; } static interface SimpleGestureListener { void onSwipe(int direction); void onDoubleTap(); } } 

我有我类似的问题,解决scheme的工作,直到我想做其他触摸事件,如刷卡和onLongPress。 这些方法从来没有被调用,所以我不得不实现一个OnDoubleTapListener。 我做了如下:

 public class MainActivity extends Activity implements OnDoubleTapListener 

那么只需要实现三种方法

 @Override public boolean onDoubleTapEvent(MotionEvent e) { if(e.getAction()==1) { Toast.makeText(getApplicationContext(), "DOUBLE TAP",Toast.LENGTH_SHORT).show(); // TODO Auto-generated method stub // Implement code here!!! } return true; } @Override public boolean onSingleTapConfirmed(MotionEvent e) { return true; } @Override public boolean onDoubleTap(MotionEvent e) { return true; } 

只需实现onDoubleTapEvent方法。 我不知道另外两个方法何时被调用,但这对我有效

 X_View.setOnClickListener(new View.OnClickListener() { @Override public void onItemClick(View view) { long timeNow=Calendar.getInstance().getTimeInMillis(); long timeLastTapped=Long.valueOf(view.getTag().toString()); // Initially set to zero in adapter final int minDurationBetweenDoubleTap=500; if(timeLastTapped != 0) if( timeNow- timeLastTapped < minDurationBetweenDoubleTap) { Toast.makeText(getApplicationContext(), "DoubleTapped", 10).show(); } view.setTag(""+timeNow); }