美文网首页android
倒计时边框

倒计时边框

作者: WLHere | 来源:发表于2020-09-09 21:18 被阅读0次

    实现效果

    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()
                }
            }
        }
    }
    

    相关文章

      网友评论

        本文标题:倒计时边框

        本文链接:https://www.haomeiwen.com/subject/yeuyektx.html