import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.CountDownTimer
import android.widget.*
import androidx.core.view.isVisible
import kotlinx.android.synthetic.main.activity_main.*
import java.util.concurrent.TimeUnit
class MainActivity : AppCompatActivity() {
//参考网址:https://github.com/KrithikAjay/CountDownTimer
private var timeCountInMilliSeconds = 60000L
private enum class TimerStatus {
STARTED, STOPPED
private var timerStatus = TimerStatus.STOPPED
private lateinit var countDownTimer: CountDownTimer
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
imageViewReset.setOnClickListener {
reset()
imageViewStartStop.setOnClickListener {
startStop()
private fun reset() {
stopCountDownTimer()
startCountDownTimer()
private fun startStop() {
if (timerStatus == TimerStatus.STOPPED) {
setTimerValues()
setProgressBarValues()
imageViewReset.isVisible = true
imageViewStartStop.setImageResource(R.drawable.icon_stop)
editTextMinute.isEnabled = false
timerStatus = TimerStatus.STARTED
startCountDownTimer()
} else {
imageViewReset.isVisible = false
imageViewStartStop.setImageResource(R.drawable.icon_start)
editTextMinute.setEnabled(true)
timerStatus = TimerStatus.STOPPED
stopCountDownTimer()
private fun setTimerValues() {
var time = 0
if (editTextMinute.text != null) {
time = (editTextMinute.text.toString().trim()).toInt()
} else {
Toast.makeText(this, R.string.message_minutes, Toast.LENGTH_SHORT).show();
timeCountInMilliSeconds = (time * 60 * 1000).toLong()
private fun startCountDownTimer() {
countDownTimer = object : CountDownTimer(timeCountInMilliSeconds, 1000) {
override fun onTick(millisUntilFinished: Long) {
textViewTime.text = hmsTimeFormatter(millisUntilFinished).toString()
progressBar.progress = (millisUntilFinished / 1000).toInt()
seek_main.progress = (millisUntilFinished / 1000).toInt()
override fun onFinish() {
textViewTime.text = hmsTimeFormatter(timeCountInMilliSeconds).toString();
setProgressBarValues();
imageViewReset.isVisible = false
imageViewStartStop.setImageResource(R.drawable.icon_start);
editTextMinute.isEnabled = true
timerStatus = TimerStatus.STOPPED;
countDownTimer.start()
private fun setProgressBarValues() {
progressBar.max = (timeCountInMilliSeconds / 1000).toInt()
progressBar.progress = (timeCountInMilliSeconds / 1000).toInt()
seek_main.max = (timeCountInMilliSeconds / 1000).toInt()
seek_main.progress = (timeCountInMilliSeconds / 1000).toInt()
private fun stopCountDownTimer() {
countDownTimer.cancel()
private fun hmsTimeFormatter(milliSeconds: Long): Any {
val hms = String.format(
"%02d:%02d:%02d",
TimeUnit.MILLISECONDS.toHours(milliSeconds),
TimeUnit.MILLISECONDS.toMinutes(milliSeconds) - TimeUnit.HOURS.toMinutes(
TimeUnit.MILLISECONDS.toHours(
milliSeconds
TimeUnit.MILLISECONDS.toSeconds(milliSeconds) - TimeUnit.MINUTES.toSeconds(
TimeUnit.MILLISECONDS.toMinutes(
milliSeconds
return hms
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorBackground">
<com.example.myapplication24.MySeekBar
android:id="@+id/seek_main"
android:layout_width="match_parent"
android:layout_height="80dp" />
<ProgressBar
android:id="@+id/progressBar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="270dp"
android:layout_height="270dp"
android:layout_centerInParent="true"
android:background="@drawable/drawable_circle_dark_blue"
android:indeterminate="false"
android:max="100"
android:progress="100"
android:progressDrawable="@drawable/drawable_circle_yellow"
android:rotation="-90" />
<EditText
android:id="@+id/editTextMinute"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@+id/textViewTime"
android:layout_centerHorizontal="true"
android:layout_marginBottom="10dp"
android:gravity="center"
android:hint="@string/hint_minute"
android:inputType="number"
android:maxLength="15"
android:maxLines="1"
android:minEms="5"
android:text="1"
android:textColor="@color/colorYellow"
android:textColorHint="@color/colorYellow" />
<TextView
android:id="@+id/textViewTime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="00:01:00"
android:textColor="@color/colorYellow"
android:textSize="40sp" />
<ImageView
android:id="@+id/imageViewReset"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_below="@+id/textViewTime"
android:layout_centerInParent="true"
android:layout_marginTop="30dp"
android:src="@drawable/icon_reset"
android:visibility="gone" />
<ImageView
android:id="@+id/imageViewStartStop"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_below="@+id/progressBar"
android:layout_centerHorizontal="true"
android:layout_marginTop="20dp"
android:src="@drawable/icon_start" />
</RelativeLayout>
4.自定义seebar
package com.example.myapplication24
import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.Rect
import android.text.TextPaint
import android.util.AttributeSet
import androidx.appcompat.widget.AppCompatSeekBar
class MySeekBar : AppCompatSeekBar {
// 画笔
private var mPaint: Paint? = null
// 进度文字位置信息
private val mProgressTextRect: Rect = Rect()
constructor(context: Context?) : super(context!!)
constructor(context: Context?, attrs: AttributeSet?) : super(context!!, attrs)
constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(
context!!,
attrs,
defStyleAttr
init {
mPaint = TextPaint()
mPaint!!.isAntiAlias = true
mPaint!!.color = Color.parseColor("#00574B")
mPaint!!.textSize = this.thumb.intrinsicHeight.toFloat()
// 如果不设置padding,当滑动到最左边或最右边时,滑块会显示不全
/* setPadding(this.thumb.intrinsicWidth / 2, 0, this.thumb.intrinsicWidth / 2, 0)*/
@Synchronized
protected override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
val progressText: String = progress.toString()
mPaint!!.getTextBounds(progressText, 0, progressText.length, mProgressTextRect)
// 进度百分比
val progressRatio: Float = progress.toFloat() / max.toFloat()
var thumbX =
(width - paddingEnd - paddingStart) * progressRatio + paddingStart - this.thumb.intrinsicWidth / 2.0f
if (progressRatio > 0.8f) {
thumbX -= this.thumb.intrinsicHeight / 2.0f
val thumbY: Float = height / 2f - mProgressTextRect.height() / 2f
canvas.drawText(progressText, thumbX, thumbY, mPaint!!)