源码
自定义属性
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="ArcProgressView">
<attr name="android:textSize" />
<attr name="bgBorderWidth" format="dimension" />
<attr name="defaultContentColor" format="color" />
<attr name="bgBorderColor" format="color" />
<attr name="progressColor" format="color" />
<attr name="android:textColor" />
</declare-styleable>
</resources>
View(kotlin)源码
package com.example.test
import android.content.Context
import android.content.res.Resources
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.Rect
import android.util.AttributeSet
import android.util.TypedValue
import android.view.View
import kotlin.math.roundToInt
class ArcProgressView : View {
constructor(context: Context?) : super(context)
constructor(context: Context?, attrs: AttributeSet?) : this(context, attrs, 0)
constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(
context,
attrs,
defStyleAttr
) {
val obtainStyledAttributes =
context?.obtainStyledAttributes(attrs, R.styleable.ArcProgressView)
obtainStyledAttributes?.let {
textSize = it.getDimensionPixelSize(
R.styleable.ArcProgressView_android_textSize,
textSize
)
strokeWidth = it.getDimensionPixelSize(
R.styleable.ArcProgressView_bgBorderWidth,
strokeWidth.roundToInt()
).toFloat()
defaultContentColor = it.getColor(
R.styleable.ArcProgressView_defaultContentColor,
defaultContentColor
)
bgBorderColor =
it.getColor(R.styleable.ArcProgressView_bgBorderColor, bgBorderColor)
progressColor =
it.getColor(R.styleable.ArcProgressView_progressColor, progressColor)
textColor =
it.getColor(R.styleable.ArcProgressView_android_textColor, textColor)
}
obtainStyledAttributes?.recycle()
}
val paint = Paint(Paint.ANTI_ALIAS_FLAG)
var strokeWidth = dpToPx(0.5f).toFloat();
var textSize = spToPx(10f).roundToInt()
var defaultContentColor = Color.parseColor("#FFF7ED")
var bgBorderColor = Color.parseColor("#FAD29D")
var progressColor = Color.parseColor("#FAD29D")
var textColor = Color.parseColor("#FA940F")
private var progress: Int = 0
set(value) {
field = value
invalidate()
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
drawBackground(canvas)
drawProgress(canvas)
}
private fun dpToPx(dp: Float): Int {
return (Resources.getSystem().displayMetrics.density * dp + 0.5f).roundToInt()
}
private fun spToPx(sp: Float): Float {
return TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_SP,
sp,
Resources.getSystem().displayMetrics
)
}
private fun drawBackground(canvas: Canvas) {
paint.strokeWidth = strokeWidth
paint.style = Paint.Style.FILL
paint.color = defaultContentColor
canvas.drawOval(
0f + strokeWidth / 2,
0f + strokeWidth / 2,
width.toFloat() - strokeWidth / 2,
height.toFloat() - strokeWidth / 2,
paint
)
paint.style = Paint.Style.STROKE
paint.color = bgBorderColor
canvas.drawOval(
0f + strokeWidth / 2,
0f + strokeWidth / 2,
width.toFloat() - strokeWidth / 2,
height.toFloat() - strokeWidth / 2,
paint
)
}
val textBound = Rect()
private fun drawProgress(canvas: Canvas) {
paint.style = Paint.Style.FILL
paint.color = progressColor
paint.textSize = textSize.toFloat()
val progressStr = "$progress%"
paint.getTextBounds(progressStr, 0, progressStr.length, textBound)
val halfTextWidth = textBound.width() / 2f
val halfTextHeight = textBound.height() / 2f
val progressAngle = progress * 3.6f
val halfWidth = width.toFloat() / 2f
val halfHeight = height.toFloat() / 2f
canvas.drawArc(
0f,
0f,
width.toFloat(),
height.toFloat(),
270f,
progressAngle,
true,
paint
)
paint.isFakeBoldText = true
paint.color = textColor
paint.textAlign = Paint.Align.LEFT
canvas.drawText(
progressStr,
halfWidth - halfTextWidth,
halfHeight - halfTextHeight + textBound.height(),
paint
)
}
fun updateProgress(progress: Int) {
this.progress = progress
}
}
Activity布局
<com.example.test.ArcProgressView
android:layout_margin="12dp"
android:id="@+id/progress"
android:textSize="24sp"
android:textColor="@color/black"
android:layout_width="100dp"
android:layout_height="100dp"/>
Activity更新进度
progress ++
runOnUiThread({
progressView.updateProgress(progress)
})
效果图