一个简单又不简单的进度条

作者: GoMoon | 来源:发表于2019-10-16 14:38 被阅读0次

前言

要求的效果是这样的


progress_view.gif

粗看之下,好像挺简单的,先画背景、再画进度条、最后画文字,就可以了。
但细看之下,有坑,当文字的颜色和进度条相融时,还要从绿色变成白色,这可不好做。
还好Androd是有解决方案的,就是利用图形学里一个概念——PorterDuff.Mode。

PorterDuff是啥

本着学英语的态度,笔者去翻译了一下这个单词,然而并没有结果,查了资料才发现,这个单词是两个人名的组合:Thomas Porter 和 Tom Duff,这两位大神是研究图形混合的。说到这里大家应该能明白了,PorterDuff.Mode其实就是两种或多种图形混合在一起时的各种模式,这里有16种Mode,看下图(蓝色方块是Src即源图,黄色圆形是Dst即目标图):


proter-duff.png

分析

那么,如何借助PorterDuff来实现我们想要的进度条效果呢?
这里需要绘制四个图层:最底层为灰色背景,其上为绿色进度条,最上面两个图层就要用到PorterDuff。
我们可以选用SrcATop这种混合模式,按照官方解析,在SrcATop模式下,Src图像像素不覆盖Dst图像像素的部分直接丢弃 ,Src图像像素剩余部分绘制在Dst图像像素之上。所以,我们可以让绿色的文字为Dst,然后最上层画一层白色的进度条,不相交时不起作用,相交时只显示为Src的颜色,文字也就变成了白色。

代码

代码比较简单,直接贴在下面吧。

public class ProgressView extends View {
    /**
     * 圆角弧度
     */
    private static final int RADIUS = 60;

    private Paint mPaint = new Paint();

    private int mProgress;

    public ProgressView(Context context) {
        this(context, null);
    }

    public ProgressView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public void setProgress(int progress) {
        if (progress >= 0 && progress <= 100) {
            mProgress = progress;
            invalidate();
        }
    }

    @SuppressLint("DrawAllocation")
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int width = getMeasuredWidth();
        int height = getMeasuredHeight();
        //画底部背景
        mPaint.setColor(Color.LTGRAY);
        canvas.drawRoundRect( new RectF(0, 0, width, height), RADIUS, RADIUS, mPaint);
        //画进度条
        mPaint.setColor(getResources().getColor(R.color.colorPrimary));
        canvas.drawRoundRect(new RectF(0, 0, width * ((float) mProgress / 100), height), RADIUS, RADIUS, mPaint);
        //画文字图层
        mPaint.setColor(getResources().getColor(R.color.colorPrimary));
        mPaint.setTextSize(sp2px(getContext(), 20));
        mPaint.setTypeface(Typeface.DEFAULT_BOLD);
        mPaint.setTextAlign(Paint.Align.CENTER);
        Bitmap textBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        Canvas textCavas = new Canvas(textBitmap);
        String content = mProgress + "%";
        float textY = height / 2.0f - (mPaint.getFontMetricsInt().descent / 2.0f + mPaint.getFontMetricsInt().ascent / 2.0f);
        textCavas.drawText(content, width / 2.0f, textY, mPaint);
       //画最上层的白色图层,未相交时不会显示出来
        mPaint.setColor(Color.WHITE);
        mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP));
        textCavas.drawRoundRect(new RectF(0, 0, width * ((float) mProgress / 100), height), RADIUS, RADIUS, mPaint);
        //画结合后的图层
        canvas.drawBitmap(textBitmap, 0, 0, mPaint);
        mPaint.setXfermode(null);
        textBitmap.recycle();
    }

    public static int sp2px(Context context, float spValue) {
        final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
        return (int) (spValue * fontScale + 0.5f);
    }
}

相关文章

  • 一个简单又不简单的进度条

    前言 要求的效果是这样的 粗看之下,好像挺简单的,先画背景、再画进度条、最后画文字,就可以了。但细看之下,有坑,当...

  • 简单又不简单

    有两件事是永远有市场的,教女人变美和教男人赚钱,从各种流行的网络课也可见一斑。作为成年的男人,赚钱当然是非常重要的...

  • unity 异步加载进度条

    一个超好用的游戏加载进度条脚本,调用简单

  • 简单又不简单的幸福

    喜欢和爱情到底是什么?我们应该怎样理解,又该怎样表达? 我想大部分人的谈对象标准,第一先看颜值吧?如果长得不...

  • 看似简单又不简单

    遇到困难别太抱怨、面对逆境不乐观积极的话,肯定会被生活抛弃,既然来到这个世界上了,就努力的往前走,拼一把。 生活里...

  • 投资,简单又不简单

    一简单理解价值投资:如果用通俗的说法来解释"价值投资",就是占确定性的便宜的投资,价值投资就是占便宜投资。当然占这...

  • 小程序 | 365笔记第4天 | progress、button

    #### progress 进度条。 简单的进度条展示 wxml: button组件: button 按钮。 注1...

  • iOS 文字可根据进度改变颜色的进度条

    日常记录工程中遇到的问题~~先上效果图: 简单解释:一个进度条view,要求进度条上的文字需要适应进度条的背景颜色...

  • Notification中更新进度条

    有时我们在下载的时候可以在通知里看到进度条信息,我这里做了一个简单更新进度条的通知。 进度条布局如下notific...

  • 简单进度条

    ![Uploading 屏幕快照 2016-03-14 09.45.52 PM_234609.png . . .]...

网友评论

    本文标题:一个简单又不简单的进度条

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