学习|Android中实现进度条按钮功能(kotlin)

  • 2019 年 12 月 11 日
  • 笔记

本文长度为1029,预计阅读4分钟

Android中实现按钮进度条

前面几章做了检测TTS及怎么样进度条下载的文章,原想结合几个知识点做一个实战操作,模仿应用宝等手机助手的那种列表下载方式,计划中发现有一环是需要实现个一按钮进度条的方式,看了看以前没有相关的东西,那这篇我们就在看看Android怎么实现按钮进度条的功能。

实现效果

实现思路

要实现ProgressBar加上Button的方式,我们需要自定义类继承自View

然后在进度条滚动的时候进行样式布局的重画

创建xml的自定义属性和点击的接口监听事件

实现按钮进度条,并重新按钮的事件

划重点

我这里实现的是一个简单的方式,可以在这个基础上加上自己的一些新的设计,比如说加载进度条时的颜色和背景色重设,按钮在不同状态下的不同颜色,进度条中状态的监听等方法实现。

代码演示

ProgressButton

package dem.vac.progressbutton      import android.annotation.SuppressLint  import android.content.Context  import android.graphics.Canvas  import android.graphics.Color  import android.graphics.Paint  import android.graphics.RectF  import android.util.AttributeSet  import android.view.MotionEvent  import android.view.View      class ProgressButton : View {        constructor(context: Context?, attrs: AttributeSet?) : super( context, attrs){          init(context!!, attrs!!)      }          constructor(context: Context?, attrs: AttributeSet?, defStyle: Int) : super(context, attrs){          init(context!!, attrs!!)      }          private lateinit var fm: Paint.FontMetrics      private var progress = 0      private var textColor: Int = Color.WHITE      private var paint: Paint? = null      private var textSize: Float = 10f      private var foreground = 0      private var backgroundcolor = 0      private var text: String? = null      private var max = 100      private val corner = 5 // 圆角的弧度      private var buttonClickListener: OnProgressButtonClickListener? = null          private fun init(          context: Context,          attrs: AttributeSet      ) {          val typedArray =              context.obtainStyledAttributes(attrs, R.styleable.ProgressButton)          backgroundcolor = typedArray.getInteger(              R.styleable.ProgressButton_backgroundcolor,              Color.parseColor("#C6C6C6")          )          foreground = typedArray.getInteger(              R.styleable.ProgressButton_foreground,              Color.rgb(20, 131, 214)          )          textColor = typedArray.getInteger(              R.styleable.ProgressButton_textcolor,              Color.WHITE          )          max = typedArray.getInteger(R.styleable.ProgressButton_max, 100)          progress = typedArray.getInteger(R.styleable.ProgressButton_progress, 0)          text = typedArray.getString(R.styleable.ProgressButton_text)          textSize = typedArray.getDimension(R.styleable.ProgressButton_textSize, 20f)          typedArray.recycle()      }        @SuppressLint("DrawAllocation")      override fun onDraw(canvas: Canvas) {          super.onDraw(canvas)          paint = Paint()          paint!!.setAntiAlias(true)          paint!!.setStrokeWidth(5f)          /**           * 绘制背景           */          var oval = RectF(0F, 0F, width.toFloat(), height.toFloat())          paint!!.setColor(this.backgroundcolor)          canvas.drawRoundRect(oval, corner.toFloat(), corner.toFloat(), paint)          /***           * 绘制进度值           */          paint!!.setColor(foreground)          if (progress <= corner) {              oval = RectF(                  0F,                  (corner - progress).toFloat(),                  (width * progress / max).toFloat(),                  (height                          - corner + progress).toFloat()              )              canvas.drawRoundRect(oval, progress.toFloat(), progress.toFloat(), paint)          } else {              oval = RectF(                  0F, 0F,                  (width * progress / max).toFloat(),                  height.toFloat()              )              canvas.drawRoundRect(oval, corner.toFloat(), corner.toFloat(), paint)          }          /***           * 绘制文本           */          if ("" == text || text == null) {              return          }          paint!!.setTextSize(textSize)          fm = paint!!.getFontMetrics()          paint!!.setColor(textColor)          val textCenterVerticalBaselineY =              height / 2 - fm.descent + (fm.descent - fm.ascent) / 2          canvas.drawText(              text,              (measuredWidth - paint!!.measureText(text)) / 2,              textCenterVerticalBaselineY,              paint          )      }        /**       * 设置最大值       *       * @param max       */      fun setMax(max: Int) {          this.max = max      }        /**       * 设置文本提示信息       *       * @param text       */      fun setText(text: String?) {          this.text = text      }        /**       * 设置进度条的颜色值       *       * @param color       */      fun setForeground(color: Int) {          foreground = color      }        /**       * 设置进度条的背景色       */      override fun setBackgroundColor(color: Int) {          this.backgroundcolor = color      }        /***       * 设置文本的大小       */      fun setTextSize(size: Int) {          textSize = size.toFloat()      }        /**       * 设置文本的颜色值       *       * @param color       */      fun setTextColor(color: Int) {          textColor = color      }        /**       * 设置进度值       *       * @param progress       */      fun setProgress(progress: Int) {          if (progress > max) {              return          }          this.progress = progress          //设置进度之后,要求UI强制进行重绘          postInvalidate()      }        fun getMax(): Int {          return max      }        fun getProgress(): Int {          return progress      }        @SuppressLint("ClickableViewAccessibility")      override fun onTouchEvent(event: MotionEvent): Boolean {          when (event.action) {              MotionEvent.ACTION_UP -> buttonClickListener!!.onClickListener()              else -> {              }          }          return true      }        fun setOnProgressButtonClickListener(clickListener: OnProgressButtonClickListener) {          buttonClickListener = clickListener      }          interface OnProgressButtonClickListener {          fun onClickListener()      }    }

自定义属性attr

我们在Android的res–values下面创建一个attr.xml,名称起什么倒是无所谓

<?xml version="1.0" encoding="utf-8"?>  <resources>      <declare-styleable name="ProgressButton">          <attr name="backgroundcolor" format="color"  />          <attr name="foreground" />          <attr name="textcolor" format="color" />          <attr name="max" />          <attr name="progress" />          <attr name="textSize" />          <attr name="text" format="string" />      </declare-styleable>  </resources>

通过上面两步,我们的ProgressButton的自定义控件就实现了,接下来我们就看看怎么去使用。

ProgressButton使用

微卡智享

activity_main.xml

在主窗体的布局文件中可以直接就加入我们刚才已经生成的ProgressButton

<?xml version="1.0" encoding="utf-8"?>  <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"      xmlns:app="http://schemas.android.com/apk/res-auto"      xmlns:tools="http://schemas.android.com/tools"      android:layout_width="match_parent"      android:layout_height="match_parent"      android:orientation="vertical"      tools:context=".MainActivity">        <TextView          android:layout_width="wrap_content"          android:layout_height="wrap_content"          android:text="Hello World!"          app:layout_constraintBottom_toBottomOf="parent"          app:layout_constraintLeft_toLeftOf="parent"          app:layout_constraintRight_toRightOf="parent"          app:layout_constraintTop_toTopOf="parent" />        <dem.vac.progressbutton.ProgressButton          android:layout_gravity="center"          android:layout_width="100dp"          android:layout_height="50dp"          app:backgroundcolor="@color/colorLightSkyBlue"          app:foreground="@color/colorRoyalBlue"          app:textcolor="@color/colorWhite"          app:text="点击开始"          android:id="@+id/progressbtn" />    </LinearLayout>

MainActivity.kt

接下来看看我们主程序的使用代码

package dem.vac.progressbutton    import androidx.appcompat.app.AppCompatActivity  import android.os.Bundle  import kotlin.concurrent.thread    class MainActivity : AppCompatActivity() {        lateinit var probtn: ProgressButton        override fun onCreate(savedInstanceState: Bundle?) {          super.onCreate(savedInstanceState)          setContentView(R.layout.activity_main)            probtn = findViewById(R.id.progressbtn)          probtn.setOnProgressButtonClickListener(object :              ProgressButton.OnProgressButtonClickListener {              override fun onClickListener() {                  thread {                      for (i in 1..100) {                          probtn.setProgress(i)                          probtn.setText("当前$i")                          Thread.sleep(50)                      }                  }              }          })      }    }

代码中我们直接就调用到ProgressButton,然后重写了onProgressButtonClickListerner事件,事件中我们开启了一个线程,做了一1到100的循环,调用到的效果就是我们文章开头的那个动图效果。