让最后一根手指触摸屏幕

Getting the last finger touching the screen

我需要进行控制,但多点触控有问题。

概念很简单:

当用户执行以下操作时会出现问题:

我想要一个代码,它只获取最后一个手指在屏幕上的'X'位置

我的实际代码:

    @Override
public boolean onTouchEvent(MotionEvent event)
{
    int index = MotionEventCompat.getPointerCount(event) - 1;

    float x = (int) MotionEventCompat.getX(event, index);       
    @SuppressWarnings("deprecation")
    int ancho = AEngine.display.getWidth();

    switch (MotionEventCompat.getActionMasked(event))
    {
        case MotionEvent.ACTION_DOWN:
            if (gameView != null)
                gameView.touchNave(x, ancho);
            break;
        case MotionEvent.ACTION_POINTER_DOWN:
            if (gameView != null)
                gameView.touchNave(x, ancho);
            break;
        case MotionEvent.ACTION_MOVE:
            if (gameView != null)
                gameView.touchNave(x, ancho);
            break;

        case MotionEvent.ACTION_UP:
            Nave.estado = AEngine.NAVE_STAY;
            break;
        case MotionEvent.ACTION_POINTER_UP:
            Nave.estado = AEngine.NAVE_STAY;
            break;
    }


    return false;
}

我认为 "the LAST finger in the screen" 你指的是最近 ACTION_DOWN/ACTION_POINTER_DOWN 时间的手指。

每次获得 DOWN/POINTER_DOWN 事件时,使用方法 getActionIndex() 获取操作指针的 ID,然后 getPointerID(),将其保存在字段 "lastActionDownId" 中.

然后,在调用touchNave()之前,用findPointerIndex(lastActionDownId)获取最后一个索引。然后将 getX(int index) 与该方法调用的结果一起使用。

我是通过使用 LinkedHashMap 并使用它的最后一项代码制作的:

LinkedHashMap<Integer, Float> al = new LinkedHashMap<Integer, Float>();
@Override
public boolean onTouchEvent(MotionEvent event)
{
    int index = MotionEventCompat.getActionIndex(event);
    int id = event.getPointerId(index);

    float x = (int) MotionEventCompat.getX(event, index);


    @SuppressWarnings("deprecation")
    int ancho = AEngine.display.getWidth();

    switch (MotionEventCompat.getActionMasked(event))
    {
        case MotionEvent.ACTION_DOWN:
            anadir(id,x);               
            break;
        case MotionEvent.ACTION_POINTER_DOWN:
            anadir(id,x);
            break;

        case MotionEvent.ACTION_UP:
            al.remove(id);
            break;
        case MotionEvent.ACTION_POINTER_UP:         
            al.remove(id);
            break;
    }

    if(al.size() > 0)
    {
        if (gameView != null)
            gameView.touchNave(getX(al), ancho);
    }
    else 
    {
        Nave.estado = AEngine.NAVE_STAY;
    }

    return false;
}
public float getX(LinkedHashMap<Integer,Float> map) {
    Iterator<Map.Entry<Integer,Float>> iterator = map.entrySet().iterator();
    float x = 0;
    while (iterator.hasNext()) {
        x = iterator.next().getValue();
    }
    return x;
}

public void anadir(int id,float x)
{
    if (al.size() > 0 || !al.containsKey(id))
    {
        al.put(id, x);  
        Log.e("WTF",Integer.toString(id)+ "añadido");
    } 
}

一直没有想到好的解决办法,最后写的比较长class。这看起来很奇怪,但是当你想正确计算手指数量并考虑抬起手指时,所以如果你给出触摸事件编号,如 #1 和 #2、#3 等,你需要知道手指 #2 被抬起,因此手指 # 1 和 #3 是有效事件,下一次手指触摸是手指 #2 再次返回。

很多事情都是用多根手指做的,如果以天真的方式进行操作,会突然将一根手指的位置传送到屏幕上,因为您按不同的顺序拾取触摸。特别是如果您想存储有关这些触摸的信息。

public class TouchTrack {

    private static final int INVALID = -1;
    private static final int POINTERMAX = 5;

    HashMap<Integer, TouchData> touches = new HashMap<>();
    ArrayList<TouchData> fingers = new ArrayList<>(POINTERMAX);


    public void setEventPointers(MotionEvent event) {
        int count = event.getPointerCount();
        count = Math.min(count, POINTERMAX);
        for (int i = 0; i < count; i++) {
            int id = event.getPointerId(i);
            TouchData td = touches.get(id);
            if (td == null) {
                //Log.e("Touch", "Log does not have records for ID: " + id);
                return;
            }
            td.x = event.getX(i);
            td.y = event.getY(i);
        }
    }

    public void setLostPointer(MotionEvent event) {
        int index = event.getActionIndex();
        if (index >= POINTERMAX) return;
        int id = event.getPointerId(index);
        TouchData finger = touches.get(id);
        finger.id = INVALID;
    }

    public void setNewPointer(MotionEvent event) {
        int index = event.getActionIndex();
        if (index >= POINTERMAX) return;
        int id = event.getPointerId(index);

        for (int i = 0; i < POINTERMAX; i++) {
            TouchData finger = fingers.get(i);
            if (finger.id == INVALID) {
                finger.id = id;
                finger.x = event.getX();
                finger.y = event.getY();
                touches.put(id, finger);
                break;
            }
        }
    }

    public double lastEventX(int requestIndex) {
        if ((requestIndex >= 0) && (requestIndex < POINTERMAX)) {
            TouchData td = fingers.get(requestIndex);
            if (td == null) return 0;
            return td.x;
        }
        return 0;
    }

    public double lastEventY(int requestIndex) {
        if ((requestIndex >= 0) && (requestIndex < POINTERMAX)) {
            TouchData td = fingers.get(requestIndex);
            if (td == null) return 0;
            return td.y;
        }
        return 0;
    }

    public boolean isPointerActive(int requestIndex) {
        if ((requestIndex >= 0) && (requestIndex < POINTERMAX)) {
            TouchData td = fingers.get(requestIndex);
            if (td == null) return false;
            return td.id != INVALID;
        }
        return false;
    }

    public void start(float x, float y) {
        touches.clear();
        fingers.clear();
        for (int i = 0; i < POINTERMAX; i++) {
            fingers.add(new TouchData(x, y));
        }
    }

    public void stop() {
        touches.clear();
        fingers.clear();
    }

    public class TouchData {
        static final int INVALID = -1;
        public int id = INVALID;
        public double x = 0;
        public double y = 0;

        public TouchData(double x, double y) {
            this.x = x;
            this.y = y;
        }
    }
}