双波纹分离字体进度条

先上个效果图看看

这里写图片描述
直接上代码了,比较忙没时间详细剖析~~相信大家能看懂

//核心部分

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        drawCircle(canvas);
        drawLightWave(canvas);
        drawDarkWave(canvas);
    }

 /**
     * 绘制浅色波浪(贝塞尔曲线)
     *
     * @param canvas
     */
    private void drawLightWave(Canvas canvas) {
        mWavePaint.setColor(LightWaveColor);
        //从右向左的水波位移应该被减去
        drawWave(canvas, mWavePaint, mLightPoints, isR2L ? -mLightWaveOffset : mLightWaveOffset);
    }

    @TargetApi(Build.VERSION_CODES.KITKAT)
    private void drawWave(Canvas canvas, Paint paint, Point[] points, float waveOffset) {
        mWaveLimitPath.reset();
        mWavePath.reset();
        float height = lockWave ? 0 : mRadius - 2 * mRadius * mPercent;
        //moveTo和lineTo绘制出水波区域矩形
        mWavePath.moveTo(points[0].x + waveOffset, points[0].y + height);

        for (int i = 1; i < mAllPointCount; i += 2) {
            mWavePath.quadTo(points[i].x + waveOffset, points[i].y + height,
                    points[i + 1].x + waveOffset, points[i + 1].y + height);
        }
        mWavePath.lineTo(points[mAllPointCount - 1].x, points[mAllPointCount - 1].y + height);
        //不管如何移动,波浪与圆路径的交集底部永远固定,否则会造成上移的时候底部为空的情况
        mWavePath.lineTo(points[mAllPointCount - 1].x, mCenterPoint.y + mRadius);
        mWavePath.lineTo(points[0].x, mCenterPoint.y + mRadius);
        mWavePath.close();
        mWaveLimitPath.addCircle(mCenterPoint.x, mCenterPoint.y, mRadius, Path.Direction.CW);
        //取该圆与波浪路径的交集,形成波浪在圆内的效果
        mWaveLimitPath.op(mWavePath, Path.Op.INTERSECT);
        canvas.drawPath(mWaveLimitPath, paint);
    }

/**
     * 绘制深色波浪(贝塞尔曲线)
     *
     * @param canvas
     */
    private void drawDarkWave(Canvas canvas) {
        //底部的字
        mPercentPaint.setColor(Color.RED);
        String text = "24GB";
        drawCenterText(canvas, mPercentPaint, text);
        //上层的字
        mPercentPaint.setColor(Color.WHITE);
        //生成闭合波浪路径
        mWavePath = getActionPath(currentPercent);
        mWavePaint.setColor(DarkWaveColor);
        //新建图层实现离屏缓冲
        int flag = canvas.saveLayer(0, 0, canvas.getWidth(), canvas.getHeight(), null, Canvas.ALL_SAVE_FLAG);
        //绘制蓝色波浪
        canvas.drawPath(mWavePath, mWavePaint);
        mWavePaint.setXfermode(xfermode);
        //用带有SRC_IN模式的画笔绘制圆形图像,这样圆和波浪相交的地方就只显示圆了
        canvas.drawBitmap(bitmap, 0, 0, mWavePaint);
        mPercentPaint.setXfermode(xfermode_text);
        //用带有SRC_ATOP的文字画笔绘制文字,这样在圆形波浪和文字相交的地方绘制文字,在不相交的地方绘制圆形波浪
        drawCenterText(canvas, mPercentPaint, text);
        //合并图层到canvas上
        canvas.restoreToCount(flag);

        mPercentPaint.setXfermode(null);
        mWavePaint.setXfermode(null);
    }

    private Path getActionPath(float percent) {
        Path path = new Path();
        int x = -mWidth;
        //当前x点坐标(根据动画进度水平推移,一个动画周期推移的距离为一个mWidth)
        x += percent * mWidth;
        //波形的起点
        path.moveTo(x, mHeight / 2);
        //控制点的相对宽度
        int quadWidth = mWidth / 4;
        //控制点的相对高度
        int quadHeight = mHeight / 20 * 3;
        //第一个周期
        path.rQuadTo(quadWidth, quadHeight, quadWidth * 2, 0);
        path.rQuadTo(quadWidth, -quadHeight, quadWidth * 2, 0);
        //第二个周期
        path.rQuadTo(quadWidth, quadHeight, quadWidth * 2, 0);
        path.rQuadTo(quadWidth, -quadHeight, quadWidth * 2, 0);
        //右侧的直线
        path.lineTo(x + mWidth * 2, mHeight);
        //下边的直线
        path.lineTo(x, mHeight);
        //自动闭合补出左边的直线
        path.close();

        return path;
    }

    private void drawCenterText(Canvas canvas, Paint textPaint, String text) {
        Rect rect = new Rect(0, 0, mWidth, mHeight);
        textPaint.setTextAlign(Paint.Align.CENTER);

        Paint.FontMetrics fontMetrics = textPaint.getFontMetrics();
        //文字框距顶部文字基线的距离
        float top = fontMetrics.top;
        //文字框底部距文字基线的距离
        float bottom = fontMetrics.bottom;
        int centerY = (int) (rect.centerY() - top / 2 - bottom / 2);

        canvas.drawText(text, rect.centerX(), centerY, textPaint);
    }

    /**
     * 绘制圆形bitmap
     *
     * @param width
     * @param height
     * @return
     */
    private Bitmap getCircleBitmap(int width, int height) {
        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
//      bitmap.eraseColor(Color.parseColor("#FF0000"));//填充颜色
        Canvas canvas = new Canvas(bitmap);
        canvas.drawCircle(width / 2, height / 2, width / 2, mWavePaint);
        return bitmap;
    }

完整代码下载地址

直接新建一个类复制进去就可以直接使用,其中还有一点点不完善的地方,待后续更新文章

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值