回合时间和总时间不匹配(倒计时|总延迟)

时间:2018-03-22 10:18:59

标签: android kotlin countdowntimer

所以我有一个倒计时器,用户可以选择他们想要的轮数,每个轮的时间和休息时间。这一切都有效,而且很棒。

我创建了第二个文本视图,用户可以看到它的总长度。

我的问题是:每次我的textview(带有回合的那个)改变它都会产生一定的延迟,这使得我的其他textview(总时间)每轮留下几秒钟(虽然它工作正常但是它只是延迟)。

我知道这是一个问题,textview有轮次而不是总时间,但我无法弄清楚原因。

有人可以看看吗?

这是一张图片,你可以看到我的总计时器还剩3个。 Problem here

谢谢

class MainActivity : Activity(), SensorEventListener {
    private var textViewTime: TextView? = null
    private var textViewTotalTime: TextView? = null
    private var textViewRounds: TextView? = null
    private var textViewWorkPreview: TextView? = null
    private var textViewRestPreview: TextView? = null
    private var timeLeftPanel: LinearLayout? = null
    private var buttonRun: Button? = null
    private var buttonReset: Button? = null
    private var buttonSettings: Button? = null
    private var running = false
    private var prep: Boolean = false
    private var runTime: String? = null
    //try total
    private var runTimeTotal: String? = null
    private var restTime: String? = null
    private var workTimeMillis: Long = 0
    private var restTimeMillis: Long = 0
    private var intervalMillis: Long = 0
    private var prepTimeMillis: Long = 0
    private var endRoundWarnMillis: Long = 0
    private var state: State? = null
    private var roundCurrent: Int = 0
    private var roundsTotal: Int = 0

    private var workTimer: Counter? = null
    private var restTimer: Counter? = null
    private var prepTimer: Counter? = null

    private var soundPool: SoundPool? = null
    private var loaded: Boolean = false
    private var alertPlayed: Boolean = false
    private var mute: Boolean = false
    private var proximity: Boolean = false
    private var soundAlertId: Int = 0
    private var soundBellId: Int = 0

    private var runtimeTotalMillis : Long = 0

    lateinit var sp: SharedPreferences
    private var v: Vibrator? = null
    private val vPattern = longArrayOf(0, 300, 100, 300, 100, 300)
    private var sensorManager: SensorManager? = null
    private var proximitySensor: Sensor? = null

    // TempTimer object for pausing and resuming
    private var tempMillisLeft: Long = 0

    private enum class State {
        REST, WORK, PREP, DONE
    }

    // SensorEventListener Override Methods
    override fun onSensorChanged(event: SensorEvent) {
        if (event.values[0] == 0f && proximity) {
            if (prepTimer == null && roundCurrent == 1 && state == State.PREP) {
                prepTimer = Counter(prepTimeMillis, intervalMillis)
                running = true
                prepTimer!!.start()
                setTextViewTimeColor()
                buttonRun!!.setText(R.string.pause)
            } else if (workTimer == null && roundCurrent == 1 && state == State.WORK) {
                workTimer = Counter(workTimeMillis, intervalMillis)
                running = true
                workTimer!!.start()
                setTextViewTimeColor()
                buttonRun!!.setText(R.string.pause)
                //   playBellSoundVibrate()
            } else {
                if (!running) {
                    if (state == State.WORK) {
                        workTimerResume()
                    } else if (state == State.REST) {
                        restTimerResume()
                    } else if (state == State.PREP) {
                        prepTimerResume()
                    }
                } else {
                    if (state == State.WORK) {
                        workTimerPause()
                    } else if (state == State.REST) {
                        restTimerPause()
                    } else if (state == State.PREP) {
                        prepTimerPause()
                    }
                }
            }
        }
    }

    override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) {

    }


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        sp = PreferenceManager.getDefaultSharedPreferences(this)

        // Sets the hardware button to control music volume
        this.volumeControlStream = AudioManager.STREAM_MUSIC
//
//        soundPool = SoundPool(10, AudioManager.STREAM_MUSIC, 0)
//        soundPool!!.setOnLoadCompleteListener { soundPool, sampleId, status -> loaded = true }
//        soundAlertId = soundPool!!.load(this, R.raw.bit_alert, 1)
//        soundBellId = soundPool!!.load(this, R.raw.bit_bell, 1)

        roundCurrent = 1

        // Preview work time and rest time settings
//        textViewRestPreview = findViewById(R.id.rest_preview_text) as TextView
//        textViewWorkPreview = findViewById(R.id.work_preview_text) as TextView

        // Load shared preferences
        loadPreferences(sp)

        // Initialize Vibration on phone
        v = this.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
        timeLeftPanel = findViewById<LinearLayout>(R.id.time_panel) as LinearLayout
        textViewTime = findViewById(R.id.time_left_textView) as TextView
        textViewTime!!.text = runTime
        // try total
        textViewTotalTime = findViewById(R.id.total_time_left_textView) as TextView
        textViewTotalTime!!.text = runTimeTotal


        textViewRounds = findViewById(R.id.round_number) as TextView
        setRoundTextView()
        buttonRun = findViewById(R.id.run_button) as Button
        buttonRun!!.setText(R.string.work)
        buttonRun!!.setOnClickListener {
            if (prepTimer == null && roundCurrent == 1 && state == State.PREP) {
                prepTimer = Counter(prepTimeMillis, intervalMillis)
                running = true
                prepTimer!!.start()
                setTextViewTimeColor()
                buttonRun!!.setText(R.string.pause)
            } else if (workTimer == null && roundCurrent == 1 && state == State.WORK) {
                workTimer = Counter(workTimeMillis, intervalMillis)
                running = true
                workTimer!!.start()
                setTextViewTimeColor()
                buttonRun!!.setText(R.string.pause)
                //    playBellSoundVibrate()
            } else {
                if (!running) {
                    if (state == State.WORK) {
                        workTimerResume()
                    } else if (state == State.REST) {
                        restTimerResume()
                    } else if (state == State.PREP) {
                        prepTimerResume()
                    }
                } else {
                    if (state == State.WORK) {
                        workTimerPause()
                    } else if (state == State.REST) {
                        restTimerPause()
                    } else if (state == State.PREP) {
                        prepTimerPause()
                    }
                }
            }
        }
        buttonReset = findViewById(R.id.reset_button) as Button
        buttonReset!!.setOnClickListener {
            if (running) {
                Toast.makeText(this@MainActivity, R.string.stop_toast, Toast.LENGTH_SHORT).show()
            } else {
                cancelNullTimers()
                tempMillisLeft = workTimeMillis
                roundCurrent = 1
                setRoundTextView()
                textViewTime!!.text = runTime
                textViewTotalTime!!.text = runTimeTotal
                runtimeTotalMillis = ((roundsTotal * workTimeMillis)
                        + (roundsTotal * restTimeMillis)) - (restTimeMillis * 1)
                if (prep) {
                    state = State.PREP
                } else {
                    state = State.WORK
                }
                buttonRun!!.setText(R.string.work)
                running = false
                setTextViewTimeColor()
            }
        }
        buttonSettings = findViewById(R.id.settings_button) as Button
        buttonSettings!!.setOnClickListener {
            if (running) {
                Toast.makeText(this@MainActivity, R.string.stop_toast, Toast.LENGTH_SHORT).show()
            } else {
                val i = Intent(this@MainActivity, SettingsActivity::class.java)
                startActivity(i)
                finish()
            }
        }
    }

    fun cancelNullTimers() {
        if (restTimer != null) {
            restTimer!!.cancel()
            restTimer = null
        }
        if (workTimer != null) {
            workTimer!!.cancel()
            workTimer = null
        }
        if (prepTimer != null) {
            prepTimer!!.cancel()
            prepTimer = null
        }
    }

    override fun onResume() {
        super.onResume()
        if (proximity) {
            sensorManager!!.registerListener(this, proximitySensor, SensorManager.SENSOR_DELAY_NORMAL)
        }

    }

    override fun onPause() {
        super.onPause()
        if (proximity) {
            sensorManager!!.unregisterListener(this)
        }
    }

    override fun finish() {
        cancelNullTimers()
        super.finish()
    }

    override fun onDestroy() {
        finish()
        super.onDestroy()
    }

    override fun onCreateOptionsMenu(menu: Menu): Boolean {
        // Inflate the menu; this adds items to the action bar if it is present.
        menuInflater.inflate(R.menu.menu_main, menu)
        return true
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        val id = item.itemId


        return if (id == R.id.action_settings) {
            true
        } else super.onOptionsItemSelected(item)

    }
//
//    private fun playAlertSound() {
//        val audioManager = getSystemService(Context.AUDIO_SERVICE) as AudioManager
//        val actualVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC).toFloat()
//        val maxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC).toFloat()
//        val volume = actualVolume / maxVolume
//        if (loaded && !mute) {
//            soundPool!!.play(soundAlertId, volume, volume, 1, 0, 1f)
//        }
//    }

//    private fun playBellSoundVibrate() {
//        val audioManager = getSystemService(Context.AUDIO_SERVICE) as AudioManager
//        val actualVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC).toFloat()
//        val maxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC).toFloat()
//        val volume = actualVolume / maxVolume
//        if (loaded && !mute) {
//            soundPool!!.play(soundBellId, volume, volume, 1, 0, 1f)
//        }
//        v!!.vibrate(vPattern, -1)
//    }
    // TODO Clean up code : set restTimer/WorkTimer to null

    private fun restTimerPause() {
        tempMillisLeft = restTimer!!.millisLeft
        restTimer!!.cancel()
        buttonRun!!.setText(R.string.work)
        running = false
        setTextViewTimeColor()
    }

    private fun restTimerResume() {
        restTimer = Counter(tempMillisLeft, intervalMillis)
        running = true
        buttonRun!!.setText(R.string.pause)
        restTimer!!.start()
        setTextViewTimeColor(tempMillisLeft)
    }

    private fun prepTimerPause() {
        tempMillisLeft = prepTimer!!.millisLeft
        prepTimer!!.cancel()
        buttonRun!!.setText(R.string.work)
        running = false
        setTextViewTimeColor()
    }

    private fun prepTimerResume() {
        prepTimer = Counter(tempMillisLeft, intervalMillis)
        running = true
        buttonRun!!.setText(R.string.pause)
        prepTimer!!.start()
        setTextViewTimeColor()
    }

    private fun workTimerPause() {
        tempMillisLeft = workTimer!!.millisLeft
        workTimer!!.cancel()
        buttonRun!!.setText(R.string.work)
        running = false
        setTextViewTimeColor()
    }

    private fun workTimerResume() {
        workTimer = Counter(tempMillisLeft, intervalMillis)
        running = true
        buttonRun!!.setText(R.string.pause)
        workTimer!!.start()
        setTextViewTimeColor(tempMillisLeft)
    }

    private fun setRoundTextView() {
        textViewRounds!!.text = " $roundCurrent/$roundsTotal"
    }

    private fun setTextViewTimeColor(millis: Long) {

        if (!running) {
            timeLeftPanel!!.setBackgroundResource(R.drawable.timer_bg_gray)
        } else if (running && state == State.WORK) {
            if (millis <= endRoundWarnMillis) {
                timeLeftPanel!!.setBackgroundResource(R.drawable.timer_bg_yellow)
            } else
                timeLeftPanel!!.setBackgroundResource(R.drawable.timer_bg_green)
        } else if (running && state == State.REST) {
            if (millis <= prepTimeMillis) {
                timeLeftPanel!!.setBackgroundResource(R.drawable.timer_bg_yellow)
            } else
                timeLeftPanel!!.setBackgroundResource(R.drawable.timer_bg_red)
        }
    }

    private fun setTextViewTimeColor() {

        // Changes the background instead
        if (!running) {
            timeLeftPanel!!.setBackgroundResource(R.drawable.timer_bg_gray)
        } else if (running && state == State.WORK) {
            timeLeftPanel!!.setBackgroundResource(R.drawable.timer_bg_green)
        } else if (running && state == State.REST) {
            timeLeftPanel!!.setBackgroundResource(R.drawable.timer_bg_red)
        } else if (running && state == State.PREP) {
            timeLeftPanel!!.setBackgroundResource(R.drawable.timer_bg_yellow)
        }
    }

    private fun setTextViewTimeWarnPrep(millis: Long) {
        if (millis <= endRoundWarnMillis && state == State.WORK) {
            timeLeftPanel!!.setBackgroundResource(R.drawable.timer_bg_yellow)
        }
        if (millis <= prepTimeMillis && state == State.REST) {
            timeLeftPanel!!.setBackgroundResource(R.drawable.timer_bg_yellow)
        }

    }

    private fun loadPreferences(sp: SharedPreferences) {
        proximity = sp.getBoolean("proximity_sensor_key", true)
        if (proximity) {
            sensorManager = this.getSystemService(Context.SENSOR_SERVICE) as SensorManager
            proximitySensor = sensorManager!!.getDefaultSensor(Sensor.TYPE_PROXIMITY)
        }
        roundsTotal = Integer.parseInt(sp.getString("number_rounds_key", "10"))
        workTimeMillis = TimePreference.getMillis(sp.getString("round_time_key", "0:30"))
        restTimeMillis = TimePreference.getMillis(sp.getString("rest_time_key", "0:10"))
        //textViewWorkPreview!!.text = "Work: " + sp.getString("round_time_key", "work time")!!
        //textViewRestPreview!!.text = "Rest: " + sp.getString("rest_time_key", "rest time")!!
        mute = sp.getBoolean("mute_key", false)
        intervalMillis = 1000
        alertPlayed = false
        prep = sp.getBoolean("prep_time_key", true)
        prepTimeMillis = 10000
        if (prep) {
            state = State.PREP
        } else {
            state = State.WORK
        }
        endRoundWarnMillis = java.lang.Long.parseLong(sp.getString("warn_time_key", "20")) * 1000
        runTime = String.format("%02d:%02d",
                TimeUnit.MILLISECONDS.toMinutes(workTimeMillis),
                TimeUnit.MILLISECONDS.toSeconds(workTimeMillis) % 60)
        restTime = String.format("%02d:%02d",
                TimeUnit.MILLISECONDS.toMinutes(restTimeMillis),
                TimeUnit.MILLISECONDS.toSeconds(restTimeMillis) % 60)
        //try total
        runTimeTotal = String.format("%02d:%02d", (TimeUnit.MILLISECONDS.toMinutes(((roundsTotal * workTimeMillis)
                + (roundsTotal * restTimeMillis)) - (restTimeMillis * 1))),
                (TimeUnit.MILLISECONDS.toSeconds(((roundsTotal * workTimeMillis)
                        + (roundsTotal * restTimeMillis)) - (restTimeMillis * 1)) % 60 ) )

        runtimeTotalMillis = ((roundsTotal * workTimeMillis)
                + (roundsTotal * restTimeMillis)) - (restTimeMillis * 1)
    }

    // Counter CLASS Section

    private inner class Counter(millisInFuture: Long, countDownInterval: Long) : CountDownTimer(millisInFuture, countDownInterval) {
        private var ms: String? = null
        //try total
        private var ms1: String? = null
        var millisLeft: Long = 0
            private set
        private var mins: Long = 0
        private var secs: Long = 0
        private var mins1: Long = 0
        private var secs1: Long = 0

        override fun onFinish() {
            if (state == State.PREP) {
                if (prepTimer != null) {
                    prepTimer = null
                }
                state = State.WORK
                ms = runTime
                ms1 = runTimeTotal
                workTimer = Counter(workTimeMillis, intervalMillis)
                workTimer!!.start()

                //    playBellSoundVibrate()
                setTextViewTimeColor()
            } else if (state == State.REST && roundCurrent < roundsTotal) {
                ++roundCurrent
                if (restTimer != null) {
                    restTimer!!.cancel()
                    restTimer = null
                }
                state = State.WORK
                ms = runTime
                ms1 = runTimeTotal
                setRoundTextView()
                setTextViewTimeColor()
                workTimer = Counter(workTimeMillis, intervalMillis)
                workTimer!!.start()
                alertPlayed = false
                //       playBellSoundVibrate()
            } else if (state == State.WORK && roundCurrent < roundsTotal) {
                if (workTimer != null) {
                    workTimer!!.cancel()
                    workTimer = null
                }
                if (restTimeMillis > 0) {
                    state = State.REST
                    setRoundTextView()
                    setTextViewTimeColor()
                    ms = restTime
                    ms1 = runTimeTotal
                    restTimer = Counter(restTimeMillis, intervalMillis)
                    restTimer!!.start()
                    alertPlayed = false
//                    playBellSoundVibrate()
                } else {
                    ++roundCurrent
                    state = State.WORK
                    ms = runTime
                    ms1 = runTimeTotal
                    setRoundTextView()
                    setTextViewTimeColor()
                    workTimer = Counter(workTimeMillis, intervalMillis)
                    workTimer!!.start()
                    alertPlayed = false
                    //   playBellSoundVibrate()
                }
            } else if (roundCurrent == roundsTotal) {


                textViewTime!!.text = "DONE!"
                state = State.DONE
                alertPlayed = false
                //    playBellSoundVibrate()
                setRoundTextView()
                setTextViewTimeColor()
                running = false
                cancelNullTimers()
                ms = runTime
                ms1 = runTimeTotal
            }
        }

        override fun onTick(millisUntilFinished: Long) {
            runtimeTotalMillis -= 1000
            millisLeft = millisUntilFinished
            mins = TimeUnit.MILLISECONDS.toMinutes(millisLeft)
            secs = TimeUnit.MILLISECONDS.toSeconds(millisLeft) % 60
            mins1 = (TimeUnit.MILLISECONDS.toMinutes(runtimeTotalMillis))
            secs1 = (TimeUnit.MILLISECONDS.toSeconds((runtimeTotalMillis))  % 60 )
            ms = String.format("%02d:%02d", mins, secs)
            ms1 = String.format("%02d:%02d", mins1,secs1 )
            setTextViewTimeWarnPrep(millisLeft)

            Log.e("MINS","$mins1")
            Log.e("SECS", "$secs1")
            Log.e("MILLIS", "${TimeUnit.MILLISECONDS.toSeconds(restTimeMillis)}")
            Log.e("MILLIS", "${TimeUnit.MILLISECONDS.toSeconds(millisLeft)}")
            Log.e("MILLIS", "${TimeUnit.MILLISECONDS.toSeconds(workTimeMillis)}")

            textViewTime!!.text = ms
            if( state == State.WORK ||  state == State.REST) {
                textViewTotalTime!!.text = ms1
            }
        }
    }

}

1 个答案:

答案 0 :(得分:0)

用于设置回合的结束时间:

Calendar c = Calendar.getInstance();
c.add(Calendar.MINUTE, 10);//Replace with round time
long time = c.getTimeInMillis();

现在就抽出时间:

long currentTime = Calendar.getInstance().getTimeInMillis();

设置Culculate分钟和秒数:

long deltaT = time-currentTime;//This is in milliseconds
int minutes = deltaT/60000;
int seconds = deltaT%60000