android

倒计时边框

2020-09-09  本文已影响0人  WLHere

实现效果

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()
            }
        }
    }
}
上一篇 下一篇

猜你喜欢

热点阅读