7

ダブルクリックと 2 本指のタッチ イベントを検出する方法は知っていますが、これらを組み合わせて反応させ、誰かが 2 本の指でダブルクリックする必要があるようにするにはどうすればよいでしょうか?

デフォルトでは、Android にはクリックの 2 番目の形式として機能する長押しがありますが、私は特に 2 本指でのダブルクリックを探しています。

4

2 に答える 2

14

2本の指のダブルタップをリッスンし、GestureDetectorのように動作するシンプルで再利用可能なインターフェイスが必要でした。このように使用できるように(すべての実行可能なコードをカットアンドペースト):

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);
    }
}

SimpleTwoFingerDoubleTapDetectorを作成しました。(これは長い名前ですが、わかりやすい名前です。任意の名前に変更できます。)この新しいファイルをプロジェクト内またはライブラリとして保存します。

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();
}

まず、Android(ワンタッチ)GestureDetectorに関するいくつかのメモ:

  • AndroidのonDoubleTap()イベントは、ViewConfigurationの標準のタイムアウト値を使用します。同時に参照します。
  • 最初のタップのフィンガーダウンイベントから2番目のタップのフィンガーダウンイベントまでの経過時間を測定し、ブロードキャストonDoubleTap()してからonDoubleTapEvent()
    • onDoubleTap()2番目のタップのフィンガーダウンイベントが発生した場合にのみ発生します。
    • onDoubleTapEvent()2回目のタップ(下、移動、上)によってすべてのアクションに対して起動されます。

SimpleTwoFingerDoubleTapDetectorに関するいくつかの注意事項:

  • 私のタイムアウトは、誤ったダブルタップ通知を防ぐために、最初のフィンガーダウンイベントから最後のフィンガーアップイベントまで測定されます。これを考慮して、デフォルトのViewConfigurationダブルタップタイムアウトに少し余分な時間を追加しました。
  • AndroidのGestureDetectorは、傾斜(2つのタップの間隔)を測定します。ここではこれの必要性はわかりませんでした。また、各タップの2本の指の間の距離も確認しませんでした。
  • 放送するイベントは1つだけonTwoFingerDoubleTap()です。

最後の注意:これは、OnTouchListenerのように動作するように簡単に変更 できます。

  1. SimpleTwoFingerDoubleTapDetectorの定義を変更します。

    public abstract class SimpleTwoFingerDoubleTapListener implements OnTouchListener {
    
  2. 新しいクラス変数を追加します。

    private View mFirstView;
    
  3. ACTION_DOWNケースを変更します。

    case MotionEvent.ACTION_DOWN:
        if(mFirstDownTime == -1 || mFirstView != v || hasTimedOut(event.getEventTime())) {
            mFirstView = v;
            reset(event.getDownTime());
        }
        break;
    
  4. ケースmFirstViewの中を通過します:ACTION_UP

    onTwoFingerDoubleTap(mFirstView);
    
  5. 最後に、onTwoFingerDoubleTap()どのビューがタップされたかを反映するようにメソッドを変更します。

    public abstract void onTwoFingerDoubleTap(View v);
    
于 2012-09-23T22:32:43.723 に答える
1

これは、2 本指のダブルクリックを検出するために作成したダブルクリック リスナーです。

使用される変数:

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

アクティビティ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);
    }
};

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;
}
于 2012-09-13T20:56:50.977 に答える