我正在创建一个在Surface View上包含多个图像的游戏,我想在触摸这些图像后对其执行一些操作。为此,我实现了OnTouchEvent方法
但是,触摸我的屏幕后,我的OnTouchEvent从未被调用(通过日志确认),并且我的应用程序进入“无响应”状态并给出以下消息。
05-30 23:18:33.237 I/art (14419): Thread[5,tid=14428,WaitingInMainSignalCatcherLoop,Thread*=0xb7efb920,peer=0x12c000a0,"Signal Catcher"]: reacting to signal 3
05-30 23:18:33.425 I/art (14419): Wrote stack traces to '/data/anr/traces.txt'
将traces.txt转换为可读形式后,我可以看到OnTouchEvent已执行。
kernel: futex_wait_queue_me+0xe0/0x108
kernel: futex_wait+0x170/0x238
kernel: do_futex+0xfc/0x9fc
kernel: sys_futex+0x80/0x160
kernel: ret_fast_syscall+0x0/0x30
native: #00 pc 00012bd8 /system/lib/libc.so (syscall+28)
native: #01 pc 000166e5 /system/lib/libc.so (_Z33__pthread_cond_timedwait_relativeP14pthread_cond_tP15pthread_mutex_tPK8timespec+56)
native: #02 pc 0010714c /data/app/Mono.Android.DebugRuntime-1/lib/arm/libmonosgen-32bit-2.0.so (???)
at md55ffffa669552197909f2e017c66d83fa.MySurfaceView.n_onTouchEvent(Native method)
at android.view.View.dispatchTouchEvent(View.java:8476)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2407)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2049)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2407)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2049)
at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2369)
at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1719)
at android.app.Activity.dispatchTouchEvent(Activity.java:2752)
at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2330)
at android.view.View.dispatchPointerEvent(View.java:8671)
at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:4193)
at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:4059)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3604)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3623)
at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3740)
at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3740)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3631)
at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:3797)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3604)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3657)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3623)
在android.view.ViewRootImpl $ InputStage.apply(ViewRootImpl.java:3631)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3604)
at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:5912)
at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:5851)
at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:5822)
at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:6002)
at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:192)
at android.os.MessageQueue.nativePollOnce(Native method)
at android.os.MessageQueue.next(MessageQueue.java:143)
at android.os.Looper.loop(Looper.java:122)
at android.app.ActivityThread.main(ActivityThread.java:5343)
at java.lang.reflect.Method.invoke!(Native method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:905) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:700)
我无法确定此问题的根本原因,任何解决方案都将非常有帮助。 以下是我的代码
SurfaceView类
class MySurfaceView : SurfaceView, ISurfaceHolderCallback
{
ISurfaceHolder holder;
MySurfaceViewThread thread;
Context context;
Deck DealtDeck;
PlayerList players;
DisplayMetrics metrics;
int Screen_Center_X;
int Screen_Center_Y;
int Screen_Width;
int Screen_Height;
int Screen_Top_Middle_X;
int Screen_Top_Middle_Y;
int Screen_Bottom_Middle_X;
int Screen_Bottom_Middle_Y;
int DealtDeck_CurrentX;
int DealtDeck_CurrentY;
int DiscardDeck_CurrentX;
int DiscardDeck_CurrentY;
const int Screen_Width_Gap = 10;
const int Screen_Height_gap = 10;
float density;
int Card_Width;
int Card_Height;
Deck DiscardedDeck;
Deck MainPlayer;
int localdownanimationvalue;
int localleftanimationvalue;
private int localrightanimationvalue;
Bitmap localbottomimage=null;
Bitmap rotatedbottomimage=null;
Bitmap localrightimage = null;
Bitmap rotatedrightimage = null;
Bitmap localleftimage = null;
Bitmap rotatedleftimage = null;
Bitmap localtopleftcornerimage = null;
Bitmap rotatedtopleftcornerimage = null;
Bitmap localtopcenterimage = null;
Bitmap rotatedtopcenterimage = null;
Bitmap localtoprightcornerimage = null;
Bitmap rotatedtoprightcornerimage = null;
private const int TotalPlayer = 6;
private Cards localcard;
Deck Left_Player;
Deck Right_Player;
Deck Top_LeftCorner_Player;
Deck Top_Center_Player;
Deck Top_RightCorner_Player;
Bitmap BlueBackCard;
private new const string Tag = "MySurfaceView";
Cards TouchedCard=null;
public MySurfaceView(Context context):base(context)
{
this.context = context;
metrics = Resources.DisplayMetrics;
SetWillNotDraw(false);
Init();
}
public MySurfaceView(Context context, IAttributeSet attrs):base(context, attrs)
{
this.context=context;
metrics = Resources.DisplayMetrics;
SetWillNotDraw(false);
Init();
}
private void Init()
{
Console.WriteLine("Init method start");
// SurfaceView surfaceview = this;
holder = Holder;
holder.AddCallback(this);
this.thread = new MySurfaceViewThread(holder,this);
Focusable=true;
}
public override bool OnTouchEvent(MotionEvent e)
{
Log.Info(Tag, "Inside OnTouch Event");
float lasttouched_X, lasttouched_Y;
Cards localcard;
int index;
if(e.Action==MotionEventActions.Down)
{
Log.Info(Tag, "Down Event is triggered");
lasttouched_X = e.GetX();
lasttouched_Y = e.GetY();
TouchedCard = CardTouched((int)lasttouched_X, (int)lasttouched_Y);
}
return true;
}
private Cards CardTouched(int lasttouched_X, int lasttouched_Y)
{
int index = 0;
Cards localcard = null;
while(index<MainPlayer.CardsLeft())
{
localcard = MainPlayer.getCard(index);
if (lasttouched_X >= localcard.current_X && lasttouched_X < (localcard.current_X + localcard.Image.Width))
return localcard;
}
return null;
}
}
表面视图线程
class MySurfaceViewThread:BaseThread
{
private MySurfaceView mysurfaceview;
private ISurfaceHolder myThreadSurfaceHolder;
bool running;
private const int Max_FPS = 60;
private const int Max_Frame_Skips = 5;
private const int Frame_Period = 1000 / Max_FPS;
public MySurfaceViewThread(ISurfaceHolder paramSurfaceHolder, MySurfaceView paramSurfaceView)
{
mysurfaceview = paramSurfaceView;
myThreadSurfaceHolder = paramSurfaceHolder;
}
public override void RunThread()
{
long beginTime; // the time when the cycle begun
long timeDiff; // the time it took for the cycle to execute
int sleepTime; // ms to sleep (<0 if we're behind)
int framesSkipped; // number of frames being skipped
Canvas c;
while (running)
{
c = null;
try
{
c = myThreadSurfaceHolder.LockCanvas(null);
lock (myThreadSurfaceHolder)
{
beginTime = NanoTime();
framesSkipped = 0;
mysurfaceview.Render(c);
mysurfaceview.PostInvalidate();
timeDiff = NanoTime() - beginTime;
sleepTime = (int)(Frame_Period - timeDiff / 1000000);
if(sleepTime>0)
{
try
{
Thread.Sleep(sleepTime);
}
catch (Exception e) { }
}
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.ToString());
}
finally
{
if (c != null)
{
myThreadSurfaceHolder.UnlockCanvasAndPost(c);
}
// running = false;
}
}
}
/// <summary>
/// To Pick Time in Nano Seconds
/// picked from https://stackoverflow.com/questions/1551742/what-is-the-equivalent-to-system-nanotime-in-net
/// </summary>
/// <returns></returns>
private static long NanoTime()
{
long nano = 10000L * Stopwatch.GetTimestamp();
nano /= TimeSpan.TicksPerMillisecond;
nano *= 100L;
return nano;
}
public override void SetRunning(bool paramBoolean)
{
running = paramBoolean;
}
}
abstract class BaseThread
{
private Thread _thread;
protected BaseThread()
{
_thread = new Thread(new ThreadStart(this.RunThread));
}
// Thread methods / properties
public void Start() { _thread.Start(); }
public void Join() { _thread.Join(); }
//public bool IsAlive => _thread.IsAlive;
// Override in base class
public abstract void RunThread();
public abstract void SetRunning(bool param);
}
答案 0 :(得分:0)
似乎是这种方法的问题:
private Cards CardTouched(int lasttouched_X, int lasttouched_Y)
{
int index = 0;
Cards localcard = null;
while(index<MainPlayer.CardsLeft())
{
localcard = MainPlayer.getCard(index);
if (lasttouched_X >= localcard.current_X && lasttouched_X < (localcard.current_X + localcard.Image.Width))
return localcard;
}
return null;
}
您无需对索引进行任何操作,但是看起来您需要在每次while
迭代中对其进行更改(例如,将其index++
进行递增)