美文网首页
Android PathMeasure自定义View带动画的提交

Android PathMeasure自定义View带动画的提交

作者: 写BUG的张永 | 来源:发表于2021-08-31 13:49 被阅读0次

    利用PathMeasure来实现自定义的动画

    源码地址

    https://github.com/SHPDZY/AndroidUiDemo

    效果展示

    1630377136826.gif

    代码实现

    主要使用PathMeasure绘制View动画的执行路径,成功/失败的动画使用贝塞尔实现。

    设置view路径

    //边框路径
    val path = Path()
    path.moveTo(lineStartX, lineTopY)
    path.lineTo(lineStopX, lineTopY)
    arcRectF.left = mW - mH + padding
    arcRectF.top = padding
    arcRectF.right = mW - padding
    arcRectF.bottom = mH - padding
    path.arcTo(arcRectF, arcRtStartAng, arcSweepAng)
    pathMeasureStrokeTop = PathMeasure(path, false)
    pathMeasureStrokeLen = pathMeasureStrokeTop.length
    path.reset()
    path.moveTo(lineStopX, lineBtmY)
    path.lineTo(lineStartX, lineBtmY)
    arcRectF.left = padding
    arcRectF.top = padding
    arcRectF.right = mH + padding
    arcRectF.bottom = mH - padding
    path.arcTo(arcRectF, arcLtStartAng, arcSweepAng)
    pathMeasureStrokeBtm = PathMeasure(path, false)
    
    //对钩的路径
    path.reset()
    path.moveTo(tickLtStartX, tickLtStartY)
    path.quadTo(tickLtControlX, tickLtControlY, tickLtEndX, tickLtEndY)
    path.quadTo(tickCenX, tickCenY, tickCenEndX, tickCenEndY)
    path.quadTo(tickRtControlX, tickRtControlY, tickRtEdX, tickRtEdY)
    mPathMeasureTick = PathMeasure(path, false)
    pathMeasureTickLen = mPathMeasureTick.length
    
    // X的路径
    path.reset()
    path.moveTo(xLfStartX, xLfStartY)
    path.lineTo(xLfEdX, xLfEdY)
    pathMeasureXL = PathMeasure(path, false)
    pathMeasureXLen = pathMeasureXL.length
    path.reset()
    
    path.moveTo(xRfStartX, xRfStartY)
    path.lineTo(xRfEdX, xRfEdY)
    pathMeasureXR = PathMeasure(path, false)
    

    根据路径和动画执行进度绘制

    /**
     * 绘制边框
     */
    private fun drawStroke(canvas: Canvas) {
        getStrokePaint()
        pathMeasurePath.reset()
        pathMeasureStrokeLenRatio = pathMeasureStrokeLen * strokeRatio
        if (strokeMode == MODE_STROKE_AROUND) {
            pathMeasureStrokeLenRatio *= 2f
        }
        pathMeasureStrokeTop.getSegment(pathMeasureStrokeLenRatio, pathMeasureStrokeLen, pathMeasurePath, true)
        canvas.drawPath(pathMeasurePath, paint)
        if (strokeMode == MODE_STROKE_AROUND) {
            pathMeasureStrokeLenRatio = pathMeasureStrokeLen * max((strokeRatio - 0.5f), 0f) * 2f
        }
        pathMeasurePath.reset()
        pathMeasureStrokeBtm.getSegment(pathMeasureStrokeLenRatio, pathMeasureStrokeLen, pathMeasurePath, true)
        canvas.drawPath(pathMeasurePath, paint)
    }
    
    /**
     * 绘制成功或失败的图案
     */
    private fun drawComplete(canvas: Canvas) {
        getTickAndXPaint()
        pathMeasurePath.reset()
        if (isSuccess) {
            mPathMeasureTick.getSegment(0f, pathMeasureTickLen * tickAndXRatio, pathMeasurePath, true)
            canvas.drawPath(pathMeasurePath, paint)
            return
        }
        pathMeasureXLenRatio = pathMeasureXLen * tickAndXRatio
        pathMeasureXL.getSegment(0f, pathMeasureXLenRatio, pathMeasurePath, true)
        canvas.drawPath(pathMeasurePath, paint)
        pathMeasurePath.reset()
        pathMeasureXLenRatio = pathMeasureXLen * max(tickAndXRatio - 0.5f, 0f) * 2f
        pathMeasureXR.getSegment(0f, pathMeasureXLenRatio, pathMeasurePath, true)
        canvas.drawPath(pathMeasurePath, paint)
    }
    
    /**
     * 绘制背景
     */
    private fun drawBackground(canvas: Canvas) {
        getBacPaint()
        if (isSuccess) {
            paint.color = getColor(bacColorStart, bacColorSuccess, (strokeRatio + tickAndXRatio) / 2f)
        } else {
            paint.color = getColor(bacColorStart, bacColorError, (strokeRatio + tickAndXRatio) / 2f)
        }
        canvas.drawRoundRect(0f, 0f, mW, mH, 200f, 200f, paint)
    }
    
    /**
     * 绘制文字
     */
    private fun drawText(canvas: Canvas) {
        getTextPaint()
        val fontMetrics: Paint.FontMetrics = paint.fontMetrics
        textY = mH / 2f - (fontMetrics.ascent + fontMetrics.descent) / 2f
        paint.color = getColor(textColor, 1f - strokeRatio)
        canvas.drawText(if (strokeRatio == 0f) text else textLoading, textX, textY, paint)
    }
    

    相关文章

      网友评论

          本文标题:Android PathMeasure自定义View带动画的提交

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