实现效果
SVID_20200909_211048_1.gif
xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:elevation="0dp"
android:gravity="right|center_vertical"
android:orientation="vertical"
tools:context=".MainActivity">
<com.example.test.view.TimerBg
android:layout_width="100dp"
android:layout_height="150dp"
android:background="#0000ff" />
</LinearLayout>
code
/**
* 边框倒计时控件
*/
class TimerBg(context: Context, attrs: AttributeSet) : RelativeLayout(context, attrs) {
var totalTime = 10000// 总时间
var leftTime = 10000// 剩余时间
private val mAnglePath = Path()// 切圆角path
private val mProgressPath = Path()// 进度path
private val mProgressPaint = Paint(Paint.ANTI_ALIAS_FLAG)
private var mAngleRadius = 0f// 圆角半径
private var mAngleDiameter = 0f// 圆角直径
private var mAngleLength = 0f// 圆角边长
private val mLTAngleRect = RectF()
private val mLBAngleRect = RectF()
private val mLineWidth: Float
private var lastTime = 0L
init {
setWillNotDraw(false)
mAngleRadius = DensityUtil.dip2px(context, 10f).toFloat()
mAngleDiameter = 2 * mAngleRadius
mAngleLength = (Math.PI * mAngleRadius / 2).toFloat()
mLineWidth = DensityUtil.dip2px(context, 6f).toFloat()
mProgressPaint.let {
it.style = Paint.Style.STROKE
it.color = 0xffff0000.toInt()
it.strokeWidth = mLineWidth
}
}
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
super.onSizeChanged(w, h, oldw, oldh)
mLTAngleRect.set(0f, 0f, mAngleDiameter, mAngleDiameter)
mLBAngleRect.set(0f, h.toFloat() - mAngleDiameter, mAngleDiameter, h.toFloat())
// 设置圆角path
mAnglePath.reset()
mAnglePath.moveTo(w.toFloat(), 0f)
mAnglePath.lineTo(w.toFloat(), h.toFloat())
mAnglePath.lineTo(mAngleRadius, h.toFloat())
mAnglePath.arcTo(mLBAngleRect, 90f, 90f)
mAnglePath.lineTo(0f, mAngleRadius)
mAnglePath.arcTo(mLTAngleRect, 180f, 90f)
mAnglePath.close()
}
override fun draw(canvas: Canvas?) {
// 绘制圆角
canvas?.save()
canvas?.clipPath(mAnglePath)
super.draw(canvas)
canvas?.restore()
}
// 绘制进度条
override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)
if (canvas == null) {
return
}
if (totalTime > 0 && leftTime <= 0) {
return
}
// 设置边框范围
val left = 0f
val top = 0f
val right = canvas.width.toFloat()
val bottom = canvas.height.toFloat()
val width = right - left
val height = bottom - top
// 总边长
val totalSideLength = (width - mAngleRadius) * 2 + (height - mAngleDiameter) + mAngleLength * 2
// 获取进度
val progressPer = if (totalTime > 0) {
leftTime.toFloat() / totalTime
} else {
1f
}
// 获取进度长度
var leftProgressLength = totalSideLength * progressPer
// 重置path
mProgressPath.reset()
mProgressPath.moveTo(right, top)
// 添加path
// 从左上角开始绘制
if (leftProgressLength >= width - mAngleRadius) {
mProgressPath.lineTo(left + mAngleRadius, top)// 上边直线
leftProgressLength -= width - mAngleRadius
if (leftProgressLength >= mAngleLength) {
mProgressPath.arcTo(mLTAngleRect, 270f, -90f)// 左上角
leftProgressLength -= mAngleLength
if (leftProgressLength >= height - mAngleDiameter) {
mProgressPath.lineTo(left, bottom - mAngleRadius)// 左边直线
leftProgressLength -= height - mAngleDiameter
if (leftProgressLength >= mAngleLength) {
mProgressPath.arcTo(mLBAngleRect, 180f, -90f)// 左下角
leftProgressLength -= mAngleLength
mProgressPath.lineTo(left + mAngleRadius + leftProgressLength, bottom)// 下边直线
} else {
mProgressPath.arcTo(mLBAngleRect, 180f, -90f * leftProgressLength / mAngleLength)// 左下角
}
} else {
mProgressPath.lineTo(left, bottom - mAngleRadius - ((height - mAngleDiameter) - leftProgressLength))// 左边直线
}
} else {
mProgressPath.arcTo(mLTAngleRect, 270f, -90f * leftProgressLength / mAngleLength)// 左上角
}
} else {
mProgressPath.lineTo(left + width - leftProgressLength, top)// 上边直线
}
canvas.drawPath(mProgressPath, mProgressPaint)
if (lastTime == 0L) {
lastTime = SystemClock.elapsedRealtime()
invalidate()
} else {
val curTime = SystemClock.elapsedRealtime()
leftTime -= (curTime - lastTime).toInt()
lastTime = curTime
if (leftTime < 0) {
leftTime = 0
}
if (leftTime >= 0) {
invalidate()
}
}
}
}
网友评论