检测后退按钮在Android视图中按

时间:2017-07-18 15:21:25

标签: android kotlin

我正在编写一个使用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之后运行的时钟。我也在overDetachedFromWindow上覆盖了停止时钟,这会让问题消失,但这样做太过分了。如果用户接到电话,它也会停止时钟,赢得它,这不是我想要的。

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

2 个答案:

答案 0 :(得分:0)

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

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

答案 1 :(得分:0)

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

我将全局变量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)
        }
    }

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