仿手机扫描和打分View

作者: Yun丶Lei | 来源:发表于2018-01-15 18:16 被阅读23次
    android.png

    仿一个手机扫描打分的View,类似于手机管家打分的那种。

    直接上图

    扫描和打分

    先绘制最外的圈和内部底色圆环

    private fun drawBGCircle() {
        mCanvas.drawCircle((width / 2).toFloat(),
         (height / 2).toFloat(), 
         mRadius - mCircleStrokeWidth,
          mBGCirclePaint)
        mCanvas.drawCircle((width / 2).toFloat(), 
        (height / 2).toFloat(), 
        mRadius - mBGPaddingTop - mBGFillCirclePaint.strokeWidth / 2, 
        mBGFillCirclePaint)
    }
    

    绘制刻度线

    画一圈梯度渲染的亮暗色渐变圆弧,重绘时不断旋转,上面盖一圈背景色的刻度线,由mDegree控制暗色所在角度。

    private fun drawScaleLine() {
        if (mScore > 0) return
        mCanvas.save()
        mCanvas.translate(mCanvasTranslateX, mCanvasTranslateY)
        mScaleArcRectF.set(mPaddingLeft + mScaleArcPaint.strokeWidth / 2,
                mPaddingTop + mScaleArcPaint.strokeWidth / 2
                , width - mPaddingRight - mScaleArcPaint.strokeWidth / 2,
                height - mPaddingBottom - mScaleArcPaint.strokeWidth / 2)
        //matrix默认会在三点钟方向开始颜色的渐变,为了吻合钟表十二点钟顺时针旋转的方向,把秒针旋转的角度减去90度
        mGradientMatrix.setRotate((mDegree - 90), width / 2F, height / 2F)
        mSweepGradient?.setLocalMatrix(mGradientMatrix)
        mScaleArcPaint.shader = mSweepGradient
        mCanvas.drawArc(mScaleArcRectF, 0F, 360F, false, mScaleArcPaint)
        //画背景色刻度线
        for (i in 0..199) {
            mScaleLinePaint.color = mBackgroundColor
            mCanvas.drawLine((width / 2).toFloat(), mPaddingTop, (width / 2).toFloat(), mPaddingTop + mScaleLength, mScaleLinePaint)
            mCanvas.rotate(1.8f, (width / 2).toFloat(), (height / 2).toFloat())
        }
        mCanvas.restore()
    }
    

    绘制进度或分数

    绘制大小不同的两部分文字,让大文字居中(进度或分数),小文字(label)靠大文字右显示

    private fun drawText() {
        mTextPaint.color = mBaseTextColor
        mTextPaint.style = Paint.Style.FILL
        mTextPaint.textSize = mBaseTextSize.toFloat()
        val s = if (mScore > 0) {
            mScore.toString()
        } else {
            mScanningPercent.toString()
        }
        mTextPaint.getTextBounds(s, 0, s.length, mTextRect)
        mCanvas.drawText(s, (width / 2).toFloat() - mTextRect.width() / 2, (height / 2).toFloat() + mTextRect.height() / 2, mTextPaint)
        mTextPaint.color = mLabelTextColor
        mTextPaint.style = Paint.Style.FILL
        mTextPaint.textSize = mLabelTextSize.toFloat()
        mCanvas.drawText(mLabel, (width / 2).toFloat() + mTextRect.width() / 2 + dip(5), (height / 2).toFloat() + mTextRect.height() / 2, mTextPaint)
    }
    

    开始扫描和结束扫描

    此处开始和结束使用Timer控制,没变化一次的时间为5ms

    /**
     * 开始扫描
     */
    fun startScanning() {
        mDegree += 2f
        if (timer == null) {
            timer = Timer()
            timer?.schedule(timerTask { startScanning() }, 0, 5)
        }
        if (mDegree >= 360f) {
            mDegree = 1f
        }
    }
    
    /**
     * 停止扫描
     */
    fun stopScanning() {
        timer?.cancel()
        timer = null
    }
    

    结束扫描绘制分数

    绘制分数的原理和绘制刻度线一下,只是去掉了渐变色和变为按比例显示着色

    private fun drawScore() {
        if (mScore <= 0) return
        mCanvas.save()
        //画背景色刻度线
        for (i in 0..199) {
            mScaleLinePaint.color = if (i > mCurrDrawScore * 2) {
                mBackgroundColor
            } else {
                mLightColor
            }
            mCanvas.drawLine((width / 2).toFloat(), mPaddingTop, (width / 2).toFloat(), mPaddingTop + mScaleLength, mScaleLinePaint)
            mCanvas.rotate(1.8f, (width / 2).toFloat(), (height / 2).toFloat())
        }
        mCanvas.restore()
    
    }
    

    最后加上分数绘制动画即可,此处使用ValueAnimator

    private fun addScore() {
        val anim = ValueAnimator.ofInt(0, mScore)
        anim.addUpdateListener {
            mCurrDrawScore = it.animatedValue as Int
            invalidate()
        }
        anim.duration = mScore * 10L
        anim.start()
    }
    

    最后附上GitHub地址ScanningProgressView

    相关文章

      网友评论

        本文标题:仿手机扫描和打分View

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