【问题标题】:Detect Back Button Press in Android View在 Android 视图中检测后退按钮按下
【发布时间】:2017-12-23 13:40:11
【问题描述】:

我正在编写一个使用 ChessClock 类的游戏应用程序。两个玩家中的每一个都有一个时钟。时钟每十分之一秒向自己发送一条消息流,如果正在运行,则减少剩余时间。当时间到期时,时钟调用父视图组中的一个方法,该方法停止时钟并设置一个标志,导致进一步的触摸事件被忽略,这样用户就不能再移动这些块了。我正在用 kotlin 写作,但我认为这对 java 程序员来说也很清楚:

class ChessClock : TextView  {
   constructor(context: Context) : super(context)
   constructor(context:Context, p:String) : this(context) {
       player = p
   }
   var player = ""
   val RUNNING   = 0
   val PAUSED    = 1
   val IDLE      = 2
   val EXPIRED   = 3
   val mInterval = 100L
   var mTime  = 0L     // in milliseconds
   var mState = IDLE
   val mHandler = Handler()
   val mUpdateTimeTask = object : Runnable {
       override fun run() {
          if (mState == RUNNING) showTime()
          mHandler.postDelayed(this, mInterval)
       }
   }

//    override fun onDetachedFromWindow() {
//        super.onDetachedFromWindow()
//        stop()
//    }

   fun setTime(minutes:Long) {
       mTime = 1000*60*minutes       // minutes to milliseconds
       mState = IDLE
       setTextColor(getResources().getColor(R.color.colorIdle))
       showTime()
       mUpdateTimeTask.run()
   }

   fun pause() {
       mState = PAUSED
       setTextColor(getResources().getColor(R.color.colorPaused))
   }

   fun start() {
        mState = RUNNING
        setTextColor(getResources().getColor(R.color.colorRunning))
   }

   fun expire() {
       mState = EXPIRED
       setTextColor(getResources().getColor(R.color.colorExpired))
       model.timeout(player)
       val aboyne = parent as AboyneView
       aboyne.gameOver(false)
    }

    fun toggle() {
        if (mState == PAUSED) start()
        else if (mState == RUNNING) pause()
    }

    fun stop() {
        mHandler.removeCallbacks(mUpdateTimeTask)
    }

    fun showTime() {
        val tenths = (mTime % 1000) / 100
        var seconds = mTime / 1000
        val minutes = seconds % 3600 / 60
        seconds %= 60
        if (minutes >= 1)
            setText(String.format("%02d:%02d",minutes, seconds))
        else
            setText(String.format("%01d:%02d:%01d",minutes, seconds, 
                 tenths))
       if (mState != RUNNING) return
       if (mTime > 0)
           mTime -= mInterval
       else
           expire()
    }
}

这很好用,但如果用户按下后退按钮然后开始新游戏,时钟显然会继续运行,即使活动的 onDestroy 方法已被调用。然后当运行时钟到期时,即使新时钟仍在运行,新游戏也会被冻结。

我是 android 新手,我不明白这是怎么回事。我原以为活动结束时时钟会被破坏。我已经测试了我对日志消息发生了什么的想法,并确认时钟在调用 onDestroy 之后运行。我还重写了 onDetachedFromWindow 以停止时钟,它使问题消失了,但这是矫枉过正。如果用户接到电话,它也会停止时钟,不是吗,这不是我想要的。

你能建议如何最好地完成我想要的吗?没有办法从活动中访问时钟吗?我曾想过在 onDestroy 中发出一些事件,并让 ChessClock 监听它,但我还不知道如何编写自定义事件和监听器。有没有更简单的方法?

【问题讨论】:

  • 我是 kotlin 语言的新手,但如果你可以将 java 代码转换为 kotlin,我将向你展示如何获取后退按钮单击侦听器
  • @BrunoFerreira 是的,那太好了。我不是一个java程序员,但我应该能够转换代码。
  • 检测java中的后退只需执行此 public void onBackPressed() { super.onBackPressed();} 如果我想在后退按钮被触发之前做一些事情,我在 super 之前添加代码。 onBackPressed();.
  • @BrunoFerreira 但是 onBackPressed 在活动中。我如何从那里访问时钟?视图似乎没有 onBackPressed 函数。

标签: android kotlin


【解决方案1】:

我不知道如何在 Kotlin 中执行此操作,但在 java 中您可以设置 Timer 每 X 毫秒执行一次 timertask,然后在需要时取消它,调用 mTimer.cancel() 您应该尝试使用它而不是 mHandler.postDelayed(this, mInterval)

这是你的做法: How to call a function after delay in Kotlin?

【讨论】:

  • 我不太明白这一点。打电话给mTimer.cancel() 比停止时钟更容易吗?如果你能给我看一个java中的例子,我相信我可以把它翻译成kotlin
【解决方案2】:

我不明白所提出的建议如何解决我的问题,但我想出了一个办法。

我将全局变量 BACK_BUTTON 初始化为 false。在活动中,我覆盖了onDestroy 以将BACK_BUTTON 设置为true。然后我修改了 ChessClock 代码来检查 BACK_BUTTON:

val mUpdateTimeTask = object : Runnable {
    override fun run() {
        if (BACK_BUTTON) expire()
        else {
            if (mState == RUNNING) showTime()
            mHandler.postDelayed(this, mInterval)
        }
    }

不是一个很好的解决方案,但在我弄清楚自定义事件之前必须这样做。据我所知,自定义事件和自定义事件侦听器是唯一干净的方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-12-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-09
    • 2021-01-19
    • 2018-08-07
    • 2013-05-10
    相关资源
    最近更新 更多