gpt4 book ai didi

java - Android 多点触控 - 不规则手指跟踪

转载 作者:行者123 更新时间:2023-12-01 05:24:57 26 4
gpt4 key购买 nike

我设计了一个简单的多点触控系统,可以跟踪手指位置及其在屏幕上的状态。程序的设计方式是,当放下两个手指时,会根据放置的顺序为它们分配一个数字。如果第一手指抬起,第二手指仍称为第二手指。

这段代码在某些时候可以完美地工作。这意味着我将在测试中运行我的应用程序,有时多点触控每次都能工作,有时使用多个手指会使应用程序完全失败。它是不规则可靠的。

我很好奇这是否是硬件错误,或者是我处理触摸输入的方式错误。源代码如下。

感谢您提供的任何帮助!

-内森·托恩奎斯特

编辑:我认为问题可能与事件监听器的注册和取消注册方式有关。有时,应用程序会崩溃,当我重新打开它时,它会再次正常工作。

EDIT2:问题只是程序的不规则程度。有时当我打开它时,它可以完美地跟踪手指。放下的第一根手指保持数字 1,第二根手指保持数字 2,依此类推。无论您在放置 2 后是否抬起手指 1,数字都保持分配状态。其他时候,您会放置两根手指,哪一根手指是 1,哪一根手指是 2 会发生变化。应用程序似乎失去了对它们的跟踪,当您将手指放在屏幕上时,数字就会切换。

EDIT3:我尝试过“触摸屏助推器”来尝试屏幕始终正确响应。并没有解决问题。

EDIT4:经过更多测试,这显然是一个代码错误。当应用程序首次启动时,它总是运行良好。设备锁定(当 Activity 暂停时)然后解锁(当 Activity 恢复时)多点触控停止工作后,我得到了一个适用于单点触摸的应用程序,但对多点触摸感到困惑。

MultitouchGameFixActivity.java

package com.nathantornquist.multitouchgame;

import android.app.Activity;
import android.content.pm.ActivityInfo;
import android.os.Bundle;
import android.view.Window;
import android.view.WindowManager;

public class MultiTouchGameFixActivity extends Activity{
/** Called when the activity is first created. */
MainGamePanel viewPanel;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

//Window state functions.
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

//This works without declaring a viewPanel instance here.
//The instance declaration is needed to pass the
//onPause and onResume commands though.
viewPanel = new MainGamePanel(this);
setContentView(viewPanel);
}

//Restarts the accelerometer after onPause
protected void onResume() {
super.onResume();
viewPanel.resume(this);

}

//Standard Method run when the Application loses focus.
//This runs the pause() function in the viewPanel so that
//the accelerometer can be paused.
protected void onPause() {
super.onPause();
viewPanel.pause();

}

protected void onDestroy() {
super.onDestroy();
viewPanel.destroy();
}
}

MainThread.java

package com.nathantornquist.multitouchgame;

import com.nathantornquist.multitouchgame.MainGamePanel;
import android.graphics.Canvas;
import android.view.SurfaceHolder;

public class MainThread extends Thread {

private SurfaceHolder surfaceHolder;
private MainGamePanel gamePanel;
private boolean running;
public boolean pleaseWait = true;
public void setRunning(boolean running) {
this.running = running;
}

public MainThread(SurfaceHolder surfaceHolder, MainGamePanel gamePanel) {
super();
this.surfaceHolder = surfaceHolder;
this.gamePanel = gamePanel;
}

@Override
public void run()
{
Canvas canvas;
while (running) {
if(!pleaseWait) {
canvas = null;
// try locking the canvas for exclusive pixel editing on the surface
try {
canvas = this.surfaceHolder.lockCanvas();
synchronized (surfaceHolder) {
// update game state
this.gamePanel.update();

// draws the canvas on the panel
this.gamePanel.onDraw(canvas);
}
} finally {
// in case of an exception the surface is not left in
// an inconsistent state
if (canvas != null) {
surfaceHolder.unlockCanvasAndPost(canvas);
}
} // end finally
}
else {
synchronized (this) {
try {
wait();
} catch (Exception e) { }
}
}
}
}
}

MainGamePanel.java

package com.nathantornquist.multitouchgame;

import android.R.string;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.util.Log;
import android.view.Display;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class MainGamePanel extends SurfaceView implements SensorEventListener, SurfaceHolder.Callback
{
//Variable Declarations.
private MainThread thread;

public int screenWidth;
public int screenHeight;

private SensorManager mSensorManager;
private Sensor mAccelerometer;

Paint paint;
public int fingerOneDown;
public int fingerTwoDown;
public int fingerThreeDown;
public int fingerFourDown;
public float fingerOneX;
public float fingerOneY;
public float fingerTwoX;
public float fingerTwoY;
public float fingerThreeX;
public float fingerThreeY;
public float fingerFourX;
public float fingerFourY;

public MainGamePanel(Context context)
{
super(context);

getHolder().addCallback(this);

thread = new MainThread(getHolder(),this);

paint = new Paint();
paint.setAntiAlias(true);

Display display = ((Activity) context).getWindowManager().getDefaultDisplay();
screenWidth = display.getWidth();
screenHeight = display.getHeight();

mSensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_FASTEST);

fingerOneDown = 0;
fingerTwoDown = 0;
fingerThreeDown = 0;
fingerFourDown = 0;
fingerOneX = 0;
fingerOneY = 0;
fingerTwoX = 0;
fingerTwoY = 0;
fingerThreeX = 0;
fingerThreeY = 0;
fingerFourX = 0;
fingerFourY = 0;

setFocusable(true);

thread.setRunning(true);
thread.start();

}

@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
}

@Override
public void surfaceCreated(SurfaceHolder holder) {
//continue the thread
synchronized (thread) {
thread.pleaseWait = false;
thread.notifyAll();
}

}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
//pause the thread
synchronized (thread) {
thread.pleaseWait = true;
}

}

@Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction() & MotionEvent.ACTION_MASK;
int pointerIndex = (event.getAction() & MotionEvent.ACTION_POINTER_ID_MASK) >> MotionEvent.ACTION_POINTER_ID_SHIFT;
int pointerId = event.getPointerId(pointerIndex);
switch (action) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_POINTER_DOWN:
Log.d("pointer id - down",Integer.toString(pointerId));
if (pointerId == 0)
{
fingerOneDown = 1;
fingerOneX = event.getX(pointerIndex);
fingerOneY = event.getY(pointerIndex);
}
if (pointerId == 1)
{
fingerTwoDown = 1;
fingerTwoX = event.getX(pointerIndex);
fingerTwoY = event.getY(pointerIndex);
}
if(pointerId == 2)
{
fingerThreeDown = 1;
fingerThreeX = event.getX(pointerIndex);
fingerThreeY = event.getY(pointerIndex);
}
if(pointerId == 3)
{
fingerFourDown = 1;
fingerFourX = event.getX(pointerIndex);
fingerFourY = event.getY(pointerIndex);
}
break;

case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
case MotionEvent.ACTION_CANCEL:
Log.d("pointer id - cancel",Integer.toString(pointerId));
if (pointerId == 0)
{
fingerOneDown = 0;
fingerOneX = event.getX(pointerIndex);
fingerOneY = event.getY(pointerIndex);
}
if (pointerId == 1)
{
fingerTwoDown = 0;
fingerTwoX = event.getX(pointerIndex);
fingerTwoY = event.getY(pointerIndex);
}
if(pointerId == 2)
{
fingerThreeDown = 0;
fingerThreeX = event.getX(pointerIndex);
fingerThreeY = event.getY(pointerIndex);
}
if(pointerId == 3)
{
fingerFourDown = 0;
fingerFourX = event.getX(pointerIndex);
fingerFourY = event.getY(pointerIndex);
}
break;

case MotionEvent.ACTION_MOVE:

int pointerCount = event.getPointerCount();
for(int i = 0; i < pointerCount; ++i)
{
pointerIndex = i;
pointerId = event.getPointerId(pointerIndex);
Log.d("pointer id - move",Integer.toString(pointerId));
if(pointerId == 0)
{
fingerOneDown = 1;
fingerOneX = event.getX(pointerIndex);
fingerOneY = event.getY(pointerIndex);
}
if(pointerId == 1)
{
fingerTwoDown = 1;
fingerTwoX = event.getX(pointerIndex);
fingerTwoY = event.getY(pointerIndex);
}
if(pointerId == 2)
{
fingerThreeDown = 1;
fingerThreeX = event.getX(pointerIndex);
fingerThreeY = event.getY(pointerIndex);
}
if(pointerId == 3)
{
fingerFourDown = 1;
fingerFourX = event.getX(pointerIndex);
fingerFourY = event.getY(pointerIndex);
}
}
break;
}
return true;
}

@Override
protected void onDraw(Canvas canvas)
{
paint.setColor(Color.WHITE);
paint.setStyle(Style.FILL);
canvas.drawPaint(paint);

if (fingerOneDown == 1)
{
paint.setColor(Color.BLUE);
paint.setTextSize(20);
canvas.drawText("1", fingerOneX, fingerOneY - 30, paint);
}

if (fingerTwoDown == 1)
{
paint.setColor(Color.RED);
paint.setTextSize(20);
canvas.drawText("2", fingerTwoX, fingerTwoY - 30, paint);
}
if (fingerThreeDown == 1)
{
paint.setColor(Color.GREEN);
paint.setTextSize(20);
canvas.drawText("3", fingerThreeX, fingerThreeY - 30, paint);
}
if (fingerFourDown == 1)
{
paint.setColor(Color.BLACK);
paint.setTextSize(20);
canvas.drawText("4", fingerFourX, fingerFourY - 30, paint);
}
}

public void update() {
}

@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}

@Override
public void onSensorChanged(SensorEvent event) {

}

public void pause() {
mSensorManager.unregisterListener(this);
}

public void resume(Context context) {
mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_FASTEST);
}

public void destroy() {
thread.setRunning(false);

if (thread != null)
{
Thread killThread = thread;
thread = null;
killThread.interrupt();
}

}


}

最佳答案

我会抛出一些想法,尽管我的 Android 技能有点缺乏......

你如何测试这个?我想是在真实设备上吧?这个可以在模拟器上测试吗?看来它很容易出现硬件问题。

如果出现故障,屏幕失去对手指的追踪,哪怕只有一毫秒,是否会重新开始索引手指?如果是这种情况,它会对手指进行随机编号,从而导致您遇到的问题。

一些想法:

  • 不跟踪食指,只保留手指及其相对位置的列表。但我猜游戏的一部分要求你保留每个手指的食指。
  • 如果您用手指失去连接,则记录下来,这将显示这是否是一个问题。我想 MotionEvent.ACTION_POINTER_UP 是您应该记录的事件。事实上,我会为每个可能的事件添加一个日志,只是为了看看发生了什么。
  • 添加一个方法,尝试确定哪个手指已放置在屏幕上,即将手指的当前位置与先前手指的已知值进行比较,如果其在阈值内,则假设是同一手指。可能还想添加一个计时器来“忘记”以前的手指。

我猜您一直在查看 Android developer blog 上的多点触控示例确保您正确使用 API?

希望能给您带来一些帮助。

关于java - Android 多点触控 - 不规则手指跟踪,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9816227/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com