Android原生ProgressBar
原生
ProgressBar
样式比较固定,主要是圆形和线条;也可以通过style
来设置样式。
style:
style | 效果 |
---|---|
@android:style/Widget.ProgressBar.Horizontal | 水平进度条 |
@android:style/Widget.ProgressBar.Small | 小型圆形进度条 |
@android:style/Widget.ProgressBar.Large | 大型圆形进度条 |
@android:style/Widget.ProgressBar.Inverse | 反色进度条 |
@android:style/Widget.ProgressBar.Small.Inverse | 反色小型圆形进度条 |
@android:style/Widget.ProgressBar.Large.Inverse | 反色大型圆形进度条 |
@android:style/Widget.Material** | MD风格 |
原生的特点就是单调,实现基本的功能,使用简单样式不复杂;要满足我们期望的效果就只能自定义View了。
自定义ProgressBar
自定义View的实现方式有很多种,继承已有的View,如ImageView,ProgressBar等等;也可以直接继承自View,在onDraw中绘制需要的效果。 要实现的效果是一个横向圆角矩形进度条,内容为渐变色。 所以在设计时要考虑到可以定义的属性:渐变色、进度等。
xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="progress">
<attr name="progress" format="float" />
<attr name="startColor" format="color" />
<attr name="endColor" format="color" />
</declare-styleable>
</resources>
View实现
这里直接继承子View,读取属性,在onDraw中绘制进度条。实现思路是通过定义
Path
来绘制裁切范围,确定绘制内容;再实现线性渐变LinearGradient
来填充进度条。然后监听手势动作onTouchEvent
,动态绘制长度。同时开放公共方法,可以动态设置进度颜色,监听进度回调,根据需求实现即可。
kotlin
package com.cs.app.view
/**
*
*/
import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.LinearGradient
import android.graphics.Paint
import android.graphics.Path
import android.graphics.RectF
import android.graphics.Shader
import android.util.AttributeSet
import android.view.View
import com.cs.app.R
class CustomProgressView(context: Context, attrs: AttributeSet?) : View(context, attrs) {
private val progressPaint = Paint()
private val backgroundPaint = Paint()
private var progress = 50f
private var startColor = Color.parseColor("#4C87B7")
private var endColor = Color.parseColor("#A3D5FE")
private var x = 0f
private var progressCallback: ProgressChange? = null
init {
// 初始化进度条画笔
progressPaint.isAntiAlias = true
progressPaint.style = Paint.Style.FILL
// 初始化背景画笔
backgroundPaint.isAntiAlias = true
backgroundPaint.style = Paint.Style.FILL
backgroundPaint.color = Color.GRAY
if (attrs != null) {
val typedArray = context.obtainStyledAttributes(attrs, R.styleable.progress)
startColor = typedArray.getColor(R.styleable.progress_startColor, startColor)
endColor = typedArray.getColor(R.styleable.progress_endColor, endColor)
progress = typedArray.getFloat(R.styleable.progress_progress, progress)
typedArray.recycle()
}
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
val width = width.toFloat()
val height = height.toFloat()
//绘制Path,限定Canvas边框
val path = Path()
path.addRoundRect(0f, 0f, width, height, height / 2, height / 2, Path.Direction.CW)
canvas.clipPath(path)
//绘制进度条
val progressRect = RectF(0f, 0f, width * progress / 100f, height)
val colors = intArrayOf(startColor, endColor)
val shader = LinearGradient(0f, 0f, width * progress / 100f, height, colors, null, Shader.TileMode.CLAMP)
progressPaint.shader = shader
canvas.drawRect(progressRect, progressPaint)
}
override fun onTouchEvent(event: android.view.MotionEvent): Boolean {
when (event.action) {
android.view.MotionEvent.ACTION_DOWN -> {
x = event.rawX
//实现点击调整进度
progress = (event.rawX - left) / width * 100
progressCallback?.onProgressChange(progress)
invalidate()
}
android.view.MotionEvent.ACTION_MOVE -> {
//实现滑动调整进度
progress = (event.rawX - left) / width * 100
progress = if (progress < 0) 0f else if (progress > 100) 100f else progress
progressCallback?.onProgressChange(progress)
invalidate()
}
else -> {}
}
return true
}
fun setProgress(progress: Float) {
this.progress = progress
invalidate()
}
fun setOnProgressChangeListener(callback: ProgressChange) {
progressCallback = callback
}
interface ProgressChange {
fun onProgressChange(progress: Float)
}
}
示例
Kotlin
class CustomViewActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_custom_view)
val progressTv: TextView = findViewById(R.id.progress_textview)
val view: CustomProgressView = findViewById(R.id.progress)
view.setProgress(50f)
view.setOnProgressChangeListener(object : CustomProgressView.ProgressChange {
override fun onProgressChange(progress: Float) {
progressTv.text = "${progress.toInt()}%"
}
})
}
}
xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:background="#0E1D3C"
android:layout_height="match_parent">
<com.cs.app.view.CustomProgressView
android:id="@+id/progress"
android:layout_width="200dp"
android:layout_height="45dp"
app:endColor="#A3D5FE"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.274"
app:progress="60"
app:startColor="#4C87B7" />
<TextView
android:id="@+id/progress_textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="100dp"
android:textColor="#ffffff"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/progress" />
</androidx.constraintlayout.widget.ConstraintLayout>
效果如下: