简体   繁体   English

如何在Android中实现双指双击?

[英]How to implement a two-finger double-click in Android?

I know how to detect a double-click and a two-finger touch event, but how can I combine these to react so somebody needs to double click with two fingers? 我知道如何检测双击和双指触摸事件,但我怎样才能将这些结合起来做出反应,这样有人需要用两根手指双击?

By default, Android has the long press to act as a second form of clicking, but I'm specifically looking for a two-finger double-click. 默认情况下,Android有长按作为第二种点击形式,但我特意寻找双指双击。

I wanted a simple and reusable interface that listens for two finger double taps and behaves like GestureDetector. 我想要一个简单且可重复使用的界面,它可以监听两个手指双击并且表现得像GestureDetector。 So that you could use it like this (all cut & paste runnable code): 这样就可以像这样使用它(所有剪切和粘贴的可运行代码):

public class Example extends Activity {
    SimpleTwoFingerDoubleTapDetector multiTouchListener = new SimpleTwoFingerDoubleTapDetector() {
        @Override
        public void onTwoFingerDoubleTap() {
            // Do what you want here, I used a Toast for demonstration
            Toast.makeText(Example.this, "Two Finger Double Tap", Toast.LENGTH_SHORT).show();
        }
    };

    // Override onCreate() and anything else you want

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if(multiTouchListener.onTouchEvent(event))
            return true;
        return super.onTouchEvent(event);
    }
}

I created SimpleTwoFingerDoubleTapDetector. 我创建了SimpleTwoFingerDoubleTapDetector。 (It's a long name, but it is descriptive. You can rename it as anything you want.) Save this new file inside your project or as a library: (这是一个很长的名称,但它是描述性的。您可以将其重命名为您想要的任何内容。)将此新文件保存在项目中或作为库:

public abstract class SimpleTwoFingerDoubleTapDetector {
    private static final int TIMEOUT = ViewConfiguration.getDoubleTapTimeout() + 100;
    private long mFirstDownTime = 0;
    private boolean mSeparateTouches = false;
    private byte mTwoFingerTapCount = 0;

    private void reset(long time) {
        mFirstDownTime = time;
        mSeparateTouches = false;
        mTwoFingerTapCount = 0;
    }

    public boolean onTouchEvent(MotionEvent event) {
        switch(event.getActionMasked()) {
        case MotionEvent.ACTION_DOWN:
            if(mFirstDownTime == 0 || event.getEventTime() - mFirstDownTime > TIMEOUT) 
                reset(event.getDownTime());
            break;
        case MotionEvent.ACTION_POINTER_UP:
            if(event.getPointerCount() == 2)  
                mTwoFingerTapCount++;
            else 
                mFirstDownTime = 0;
            break;
        case MotionEvent.ACTION_UP:
            if(!mSeparateTouches)
                mSeparateTouches = true;
            else if(mTwoFingerTapCount == 2 && event.getEventTime() - mFirstDownTime < TIMEOUT) {
                onTwoFingerDoubleTap();
                mFirstDownTime = 0;
                return true;
            }
        }               

        return false;
    }

    public abstract void onTwoFingerDoubleTap();
}

First, a few notes about Android (one-touch) GestureDetector : 首先,关于Android(一键式) GestureDetector的一些注意事项:

  • Android's onDoubleTap() event uses a standard timeout value from ViewConfiguration. Android的onDoubleTap()事件使用ViewConfiguration的标准超时值。 I refer to the same time. 我指的是同一时间。
  • They measure the elapsed time from the first tap's finger-down event to the second tap's finger-down event, and then broadcast onDoubleTap() and onDoubleTapEvent() . 它们测量从第一次敲击手指向下事件到第二次敲击手指向下事件所经过的时间,然后广播onDoubleTap()onDoubleTapEvent()
    • onDoubleTap() is fired only when the second tap's finger-down event occurs. onDoubleTap()仅在第二次敲击手指向下事件发生时触发。
    • onDoubleTapEvent() is fired for every action by the second tap: down, move, and up. 第二次点击时,每个动作都会触发onDoubleTapEvent() :向下,向上和向上。

A few notes on SimpleTwoFingerDoubleTapDetector : 关于SimpleTwoFingerDoubleTapDetector的一些注意事项

  • My timeout is measured from the first finger-down event to the last finger- up event to prevent false double-tap notifications. 我的超时是从第一个手指向下事件到最后一个手指向上事件测量的,以防止错误的双击通知。 I added a little extra time to the default ViewConfiguration double tap timeout to account for this. 我为默认的ViewConfiguration双击超时添加了一点额外的时间来解释这个问题。
  • Android's GestureDetector measures slop (how far apart the two taps are). Android的GestureDetector测量slop(两个水龙头相隔多远)。 I didn't see the need for this here, nor did I check the distance between the two fingers on each tap. 我没有看到这里的需要,也没有检查每个水龙头上两个手指之间的距离。
  • I only broadcast one event onTwoFingerDoubleTap() . 我只在onTwoFingerDoubleTap()播放了一个事件。

Final note: You can easily change this to behave like an OnTouchListener: 最后说明:您可以轻松地将其更改为OnTouchListener:

  1. Change SimpleTwoFingerDoubleTapDetector's definition: 更改SimpleTwoFingerDoubleTapDetector的定义:

     public abstract class SimpleTwoFingerDoubleTapListener implements OnTouchListener { 
  2. Add a new class variable: 添加一个新的类变量:

     private View mFirstView; 
  3. Change the ACTION_DOWN case: 更改ACTION_DOWN案例:

     case MotionEvent.ACTION_DOWN: if(mFirstDownTime == -1 || mFirstView != v || hasTimedOut(event.getEventTime())) { mFirstView = v; reset(event.getDownTime()); } break; 
  4. Pass mFirstView inside the ACTION_UP case: ACTION_UP案例中传递mFirstView

     onTwoFingerDoubleTap(mFirstView); 
  5. Last, change the onTwoFingerDoubleTap() method to reflect which View was tapped: 最后,更改onTwoFingerDoubleTap()方法以反映点击了哪个View:

     public abstract void onTwoFingerDoubleTap(View v); 

This is a double-click listener I created to detect a two-finger double click. 这是我创建的双击监听器,用于检测双指双击。

Variables used: 使用的变量:

private GestureDetector gesture;
private View.OnTouchListener gestureListener;
boolean click1 = false;
boolean click2 = false;
long first = 0;
long second = 0;

In the activity's onCreate() to register the touch events: 在活动的onCreate()中注册触摸事件:

gesture = new GestureDetector(getApplicationContext(), new SimpleOnGestureListener(){
    public boolean onDown(MotionEvent event) {
        return true;
    }
});
gestureListener = new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        return gesture.onTouchEvent(event);
    }
};

Outside of onCreate() inside the activity: 在活动内部的onCreate()之外:

@Override
public boolean onTouchEvent(MotionEvent event) {   
    try {
        int action = event.getAction() & MotionEvent.ACTION_MASK;
        //capture the event when the user lifts their fingers, not on the down press
        //to make sure they're not long pressing
        if (action == MotionEvent.ACTION_POINTER_UP) {
            //timer to get difference between clicks
            Calendar now = Calendar.getInstance();

            //detect number of fingers, change to 1 for a single-finger double-click, 3 for a triple-finger double-click, etc.
            if (event.getPointerCount() == 2) {
                if (!click1) {
                    //if this is the first click, then there hasn't been a second
                    //click yet, also record the time
                    click1 = true;
                    click2 = false;
                    first = now.getTimeInMillis(); 
                } else if (click1) {
                    //if this is the second click, record its time 
                    click2 = true;
                    second = now.getTimeInMillis();

                    //if the difference between the 2 clicks is less than 500 ms (1/2 second)
                    //Math.abs() is used because you need to be able to detect any sequence of clicks, rather than just in pairs of two
                    //(e.g. click1 could be registered as a second click if the difference between click1 and click2 > 500 but
                    //click2 and the next click1 is < 500)
                    if (Math.abs(second-first) < 500) {

                        //do something!!!!!!

                    } else if (Math.abs(second-first) >= 500) {
                        //reset to handle more clicks
                        click1 = false;
                        click2 = false;
                    }
                }
            }
        }
    } catch (Exception e){

    }
    return true;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM