让最后一根手指触摸屏幕
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;
}
}
}
我需要进行控制,但多点触控有问题。
概念很简单:
- 如果用户触摸左侧(屏幕的一半),船会向左移动
- 如果用户触摸右侧(屏幕的一半),船会向右移动。
当用户执行以下操作时会出现问题:
- 将手指放在左侧
- 不移开左手指,将手指放在右侧
- 移开左手指
- 再放左手指(我的代码无法识别,有问题)
我想要一个代码,它只获取最后一个手指在屏幕上的'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;
}
}
}