效果图如上
圆弧比较好画,drawArc随便百度一下就行,注意画线的时候用了圆角线,看起来比较好看一点.
代码如下
自定义view
private var mPaint = Paint()
private var textPaint = Paint()
private var maxValue = 100f
private var minValue = 0f
private val centerRect = Rect()
private val minRect = Rect()
private val maxRect = Rect()
private var centerText = ""
set(value) {
field = value
textPaint.getTextBounds(value, 0, value.length, centerRect)
}
var aimRatio = 0f
set(value) {
field = if (value > 1f)
1f
else
value
centerText = "${(field * (maxValue - minValue) + minValue).format()}"
ObjectAnimator.ofFloat(this, "ratio", ratio, aimRatio).apply {
duration = 500
interpolator = DecelerateInterpolator()
addUpdateListener {
ratio = it.animatedValue.toString().toFloat()
invalidate()
}
start()
}
}
var ratio = 0f
private set
var hOffset = 0
init {
mPaint.style = Paint.Style.STROKE
//设置圆角线条
mPaint.strokeCap = Paint.Cap.ROUND
mPaint.strokeWidth = 20f
textPaint.textSize = 28f
textPaint.color = Color.WHITE
val typedArray: TypedArray? = context.obtainStyledAttributes(attrs, R.styleable.CircleProgress)
ratio = typedArray?.getFloat(R.styleable.CircleProgress_ratio, 0f) ?: 0f
maxValue = typedArray?.getFloat(R.styleable.CircleProgress_maxValue, 100f) ?: 100f
minValue = typedArray?.getFloat(R.styleable.CircleProgress_minValue, 0f) ?: 0f
typedArray?.recycle()
centerText = "${(ratio * (maxValue - minValue) + minValue).format()}"
textPaint.getTextBounds(centerText, 0, centerText.length, centerRect)
textPaint.getTextBounds(minValue.toString(), 0, minValue.toString().length, minRect)
textPaint.getTextBounds(maxValue.toString(), 0, minValue.toString().length, maxRect)
//预留底部文字高度
hOffset = centerRect.bottom - centerRect.top
}
override fun onDraw(canvas: Canvas) {
//进度条背景
mPaint.color = context.resources.getColor(R.color.bg_gray)
canvas.drawArc(paddingStart + mPaint.strokeWidth / 2f, paddingTop + mPaint.strokeWidth / 2f, measuredWidth.toFloat() - paddingEnd - mPaint.strokeWidth / 2f,
measuredHeight.toFloat() - hOffset - paddingBottom - mPaint.strokeWidth / 2f, 115f, 310f, false, mPaint)
//进度条
mPaint.color = context.resources.getColor(R.color.btn_blue)
canvas.drawArc(paddingStart + mPaint.strokeWidth / 2f, paddingTop + mPaint.strokeWidth / 2f, measuredWidth.toFloat() - paddingEnd - mPaint.strokeWidth / 2f,
measuredHeight.toFloat() - hOffset - paddingBottom - mPaint.strokeWidth / 2f, 115f, 310f * ratio, false, mPaint)
//中心文字
canvas.drawText(centerText, (measuredWidth - paddingStart - paddingEnd - centerRect.right + centerRect.left) / 2f + paddingStart,
(measuredHeight - hOffset - paddingTop - paddingBottom + centerRect.bottom - centerRect.top) / 2f + paddingTop, textPaint)
//左下角文字
canvas.drawText(minValue.toString(), (measuredWidth - paddingStart - paddingEnd) * (1f - Math.sin(Math.toRadians(25.0)).toFloat()) / 2f + 5f + paddingStart - minRect.right / 2f + minRect.left / 2f,
measuredHeight - (measuredWidth - paddingStart - paddingEnd) * (1f - Math.cos(Math.toRadians(25.0)).toFloat()) / 4f - paddingBottom, textPaint)
//右下角文字
canvas.drawText(maxValue.toString(), (measuredWidth - paddingStart - paddingEnd) * (1f + Math.sin(Math.toRadians(25.0)).toFloat()) / 2f - 5f + paddingStart - maxRect.right / 2f + maxRect.left / 2f,
measuredHeight - (measuredWidth - paddingStart - paddingEnd) * (1f - Math.cos(Math.toRadians(25.0)).toFloat()) / 4f - paddingBottom, textPaint)
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
var w = MeasureSpec.getSize(widthMeasureSpec)
val wMode = MeasureSpec.getMode(widthMeasureSpec)
if (wMode == MeasureSpec.AT_MOST || wMode == MeasureSpec.UNSPECIFIED) {
w = 400
}
setMeasuredDimension(w, w + hOffset)
}
xml
<com.view.CircleProgress
android:id="@+id/cp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="@dimen/dimen_size_24"
app:ratio="0.6"
app:minValue="20"
app:maxValue="120"
android:background="@color/colorPrimaryDark"/>
<EditText
android:id="@+id/et"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="numberDecimal"
android:layout_below="@+id/cp" />
<Button
android:id="@+id/btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/et"
android:text="sure"/>
activity
mBinding.btn.setOnClickListener {
if(mBinding.et.text.toString().isNotEmpty())
mBinding.cp.aimRatio = mBinding.et.text.toString().toFloat()
}
中间的文字好定位点,下边两个文字要用到三角函数相关的东西,大家可以自己画图算算,不一定非要按我的来.
如有问题或不足之处,欢迎批评指正
网友评论