安卓仿华为天气圆弧进度条

Screenshot_20181127-172550_SimpleWar.jpg

效果图如上
圆弧比较好画,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



        

        

activity

 mBinding.btn.setOnClickListener {
            if(mBinding.et.text.toString().isNotEmpty())
            mBinding.cp.aimRatio = mBinding.et.text.toString().toFloat()
        }

中间的文字好定位点,下边两个文字要用到三角函数相关的东西,大家可以自己画图算算,不一定非要按我的来.

如有问题或不足之处,欢迎批评指正

你可能感兴趣的:(安卓仿华为天气圆弧进度条)