获取当前手指在Android上的位置

时间:2013-07-30 12:12:56

标签: java android events multi-touch

我正在开发一个需要让所有手指都在Android屏幕上的应用程序。这并不复杂,我可以用几行代码来制作它。

然而,android发送回调的方式并不是我需要的。我做了很多测试,这是我能找到的:

一旦他发出手指位置,如果没有做出“大”动作,他就不会发送onTouch事件。

此外,当手指从屏幕上移除时(例如:有3个手指,其中一个被移除),如果至少有一个剩余的手指在屏幕上移动,它似乎只发送下一个事件

我正在对手指进行一些跟踪,并与对象进行匹配,为了正确地做到这一点,我需要一直知道所有手指的位置。如果没有办法“请求”手指触摸事件,即使它没有移动,如何在没有回调事件的情况下访问当前手指位置?还有其他解决方案吗?

这是我的代码:

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

2 个答案:

答案 0 :(得分:1)

我的问题是我在移除手指后没有收到一个event所有手指位置......

经过大量测试和记录后,我发现它是真的(部分)。

每当您在SCREEN上移除手指时,发送的NEXT事件为ACTION_POINTER_UPACTION_UP,表示手指x不再触摸屏幕。

由于移除手指后没有任何动作,因此发送的最后一个MotionEventUP,也包含了删除的手指。

所以,为了解决这个问题,我检查动作是否为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;
    }

答案 1 :(得分: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;

找到这个真的是一场噩梦。但无论如何,我认为你只想要最好并帮助别人:-)))没问题。