本文长度为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的循环,调用到的效果就是我们文章开头的那个动图效果。