1

Android の画面上ですべての指を取得する必要があるアプリケーションを開発しています。これは複雑ではなく、数行のコードで作成できます。

ただし、アンドロイドがコールバックを送信する方法は、私が必要とするものではありません。私は多くのテストを行いましたが、ここに私が見つけたものがあります:

彼が指の位置を送信した後、「大きな」動きがない場合、彼は onTouch イベントを送信しません。

また、指が画面から削除された場合 (たとえば、3 本の指があり、1 本が削除された場合)、残りの指の少なくとも 1 本が画面上で移動した場合にのみ、次のイベントが送信されるように見えます。

私は指の追跡とオブジェクトとのマッチングを行っていますが、これを適切に行うには、常にすべての指の位置を知る必要があります。指が動いていないときでも指のタッチイベントを「リクエスト」する方法がない場合、コールバックイベントなしで現在の指の位置にアクセスするにはどうすればよいですか? 他の解決策はありますか?

これが私のコードです:

ArrayList<Vector3> fingerTips = new ArrayList<Vector3>();

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        final int points = event.getPointerCount();
        String out = "==========\n";

        fingerTips.clear();

        for(int i = 0; i < points; i++){
            out += "\tPoint "+i+"\t("+event.getX(i)+", "+event.getY(i) + ")\n";
            fingerTips.add( new Vector3(event.getX(i), event.getY(i)) );
        }

        Log.i(TAG, out);

        // Send touches to SurfaceView
        chwaziViewGL.onUpdateFingerTips(fingerTips);

        return true;
    }
4

2 に答える 2

1

私の問題はevent、指を取り除いた後、すべての指の位置で1つを受け取っていないことでした...

多くのテストとログ記録の後、(部分的に) それが真実であることを発見しました。

画面上で指を離すと、送信される NEXT イベントは常にACTION_POINTER_UPまたはACTION_UPであり、指xが画面に触れていないことを意味します。

指を離した後は動きがなかったので、最後MotionEventに送信されたのはUP、離された指も含む でした。

それで、それを修正するために、アクションがUPであるかどうかを確認し、すべての指を取得するループで、それが画面から削除された指であるかどうかを確認する if を作成しました。もしそうなら、私はそれを配列に追加しませんでした。

これが私の最終的なコードです:

ArrayList<Vector3> fingerTips = new ArrayList<Vector3>();

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        final int points = event.getPointerCount();

        // Check if it's an event that a finger
        // was removed, if so, set removedPoint
        int removedPoint = -1;
        final int action = event.getAction() & MotionEvent.ACTION_MASK;

        if(action == MotionEvent.ACTION_POINTER_UP || action == MotionEvent.ACTION_UP)
            removedPoint = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) 
                    >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;


        String out = "==========\n";

        fingerTips.clear();

        for(int i = 0; i < points; i++){
            // Find out pointer ID
            int pointerID = event.getPointerId(i);
            if(pointerID == MotionEvent.INVALID_POINTER_ID){
                out += "\tPoint "+pointerID+" INVALID\n";
                continue;
            }

            // Check if it's the removed finger
            if(removedPoint == i){
                out += "\tPoint "+pointerID+" REMOVED\n";
                continue;
            }

            out += "\tPoint "+pointerID+"\t("+event.getX(i)+", "+event.getY(i) + ")\n";
            fingerTips.add( new Vector3(event.getX(i), event.getY(i), pointerID) );
        }

        Log.i(TAG, out);

        // Send touches to SurfaceView
        chwaziViewGL.onUpdateFingerTips(fingerTips);

        return true;
    }
于 2013-07-30T18:14:07.557 に答える
1

申し訳ありませんが、あなたのコードには多くの費用がかかりました;-((数日後、気が狂う前にようやく問題を発見しました。このコード

final int action = event.getAction() & MotionEvent.ACTION_MASK;

if(action == MotionEvent.ACTION_POINTER_UP || action == MotionEvent.ACTION_UP)
        removedPoint = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) 
                >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;

働いたことはありませんでした!!!

なんで?getAction() からの値をマスクすると、アクションの単純な整数値になるためです。そして、この単純な値を使用して、何かで再度マスクしようとすると、まったく意味がありません!

修正は、秒のマスキングで event.getAction() を再度使用することです。

removedPoint = (event.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) 
                >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;

これを見つけるのは本当に悪夢でした。とにかく、あなたはただ最善を尽くして他の人を助けたかっただけだと思います:-))) 大丈夫です。

于 2016-03-09T21:11:02.583 に答える