在Surface View上调用OnTouchEvent时,应用程序无响应

时间:2018-09-10 18:45:51

标签: android xamarin.android surfaceview ontouchevent

我正在创建一个在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);
}

1 个答案:

答案 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++进行递增)