所以我有一个倒计时器,用户可以选择他们想要的轮数,每个轮的时间和休息时间。这一切都有效,而且很棒。
我创建了第二个文本视图,用户可以看到它的总长度。
我的问题是:每次我的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
}
}
}
}
答案 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