最近写了一个水滴效果的进度条,加了点特效,就是个简单的自定义view,用的二阶贝塞尔函数,如果有赶工期或者正好碰到类似效果需求的同伴们可以直接改改来用,提供 setProgress(float porgress)和reset()函数,已做适配,先上效果图:

然后直接上完整代码:


/**
 * author by LiuGuo
 * on 2021/4/9
 * 自定义组件:水滴进度条
 */
public class DripProgressView extends View {

    private int widthsize;
    private int heightsize;
    Context context;
    DecimalFormat decimalFormat = new DecimalFormat("00");
    public boolean isTart;
    private Paint drip_paint;
    private Paint reseve_line_paint;
    private Paint text_paint;
    private Path path0;
    private Path path1;
    private Path path2;
    private Path path3;
    private Path path4;
    boolean isFinish;
    float text_speech = 0; //文字掉下速度
    int drip_speech = 0; //水滴掉下速度
    float mDegrees = 0; //整体进度
    float line_revese_radom = 0; //横线回弹随机数
    Random random = new Random();
    private int bglColor;
    private int textColor;

    public DripProgressView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.waterProgress);
        bglColor = ta.getColor(R.styleable.waterProgress_bgColor, Color.parseColor("#33FF66"));
        textColor = ta.getColor(R.styleable.waterProgress_textColor, Color.parseColor("#ffffff"));
    }

    public DripProgressView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        init();
        widthsize = MeasureSpec.getSize(widthMeasureSpec);
        heightsize = MeasureSpec.getSize(heightMeasureSpec);
        setMeasuredDimension(widthsize, heightsize);
    }


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        path0 = new Path();
        path1 = new Path();
        path2 = new Path();
        path3 = new Path();
        path4 = new Path();

        path0.moveTo(widthsize / 2 - widthsize / 2.0625f, heightsize / 79.65f);
        path0.quadTo(widthsize / 2, heightsize / 19.9125f + line_revese_radom, widthsize / 2 + widthsize / 2.0625f, heightsize / 79.65f);

        if (isFinish) { //完成后做的动画

            path1.reset();// 重置
            path1.moveTo(widthsize / 2, heightsize / 31.86f + line_revese_radom);
            path1.quadTo(widthsize / 2 - (widthsize / 8.25f - mDegrees) - widthsize / 13.75f, heightsize / 31.86f + line_revese_radom, widthsize / 2, heightsize / 10.62f + line_revese_radom);

            path2.reset();// 重置
            path2.moveTo(widthsize / 2, heightsize / 31.86f + line_revese_radom);
            path2.quadTo(widthsize / 2 + (widthsize / 8.25f - mDegrees) + widthsize / 13.75f, heightsize / 31.86f + line_revese_radom, widthsize / 2, heightsize / 10.62f + line_revese_radom);

            path3.reset();// 重置
            path3.moveTo(widthsize / 2, heightsize / 10.62f + drip_speech);
            path3.quadTo(widthsize / 2 - widthsize / 1.83334f, heightsize / 1.99125f + mDegrees + drip_speech, widthsize / 2, heightsize / 2 + heightsize / 12.38421f + mDegrees + drip_speech);

            path4.moveTo(widthsize / 2, heightsize / 10.62f + drip_speech);
            path4.quadTo(widthsize / 2 + widthsize / 1.83334f, heightsize / 1.99125f + mDegrees + drip_speech, widthsize / 2, heightsize / 2 + heightsize / 12.38421f + mDegrees + drip_speech);

        } else {  //进行时做的动画

            path1.reset();// 重置
            path1.moveTo(widthsize / 2, heightsize / 31.86f);
            path1.quadTo(widthsize / 2 - (widthsize / 8.25f - mDegrees), heightsize / 15.93f, widthsize / 2 - (widthsize / 3.75f - mDegrees), heightsize / 4.978125f);
            path1.quadTo(widthsize / 2 - widthsize / 1.833334f, heightsize / 1.99125f + mDegrees, widthsize / 2, heightsize / 2 + heightsize / 12.38421f + mDegrees);

            path2.moveTo(widthsize / 2, heightsize / 31.86f);
            path2.quadTo(widthsize / 2 + (widthsize / 8.25f - mDegrees), heightsize / 15.93f, widthsize / 2 + (widthsize / 3.75f - mDegrees), heightsize / 4.978125f);
            path2.quadTo(widthsize / 2 + widthsize / 1.833334f, heightsize / 1.99125f + mDegrees, widthsize / 2, heightsize / 2 + heightsize / 12.38421f + mDegrees);

        }

        path1.close();
        canvas.drawPath(path1, drip_paint);
        canvas.drawPath(path2, drip_paint);
        canvas.drawPath(path3, drip_paint);
        canvas.drawPath(path4, drip_paint);
        canvas.drawPath(path0, reseve_line_paint);
        if (drip_speech >= 1) {
            canvas.drawText(decimalFormat.format(mDegrees / (heightsize / 11.37857f) * 100) + "%", widthsize / 2 - widthsize / 6.875f, heightsize / 2.450769f + text_speech, text_paint);
        } else {
            canvas.drawText(decimalFormat.format(mDegrees / (heightsize / 11.37857f) * 100) + "%", widthsize / 2 - widthsize / 8.25f, heightsize / 2.450769f + text_speech, text_paint);
        }

        if (mDegrees < heightsize / 11.37857f) {
            text_speech = mDegrees;
        } else {
            isFinish = true;
            drip_speech += 25;
            text_speech += 25;
            if (heightsize / 10.62f + drip_speech <= heightsize / 2)
                line_revese_radom = random.nextInt(20) - 3;
        }

        if (heightsize / 10.62f + drip_speech <= heightsize + heightsize / 31.86f) {
            invalidate();
        }
    }


    public void setProgress(float porgress) {
        mDegrees = porgress;
    }

    public void reset() {
        mDegrees = 0;
        text_speech = 0;
        drip_speech = 0;
        mDegrees = 0;
        line_revese_radom = 0;
        isFinish = false;
        invalidate();
    }

    BlurMaskFilter   blu=new BlurMaskFilter(1,BlurMaskFilter.Blur.SOLID);

    void init() {
        setLayerType(LAYER_TYPE_SOFTWARE, null);
        drip_paint = new Paint();
        drip_paint.setAntiAlias(true);
        drip_paint.setColor(bglColor);
        drip_paint.setStyle(Paint.Style.FILL);
        drip_paint.setFilterBitmap(true);
        drip_paint.setMaskFilter(blu);
        drip_paint.setShadowLayer(9,13,13,Color.parseColor("#55000000"));


        reseve_line_paint = new Paint();
        reseve_line_paint.setAntiAlias(true);
        reseve_line_paint.setColor(bglColor);
        reseve_line_paint.setStrokeWidth(widthsize/165f);
        reseve_line_paint.setFilterBitmap(true);
        reseve_line_paint.setMaskFilter(blu);
        reseve_line_paint.setShadowLayer(9,0,13,Color.parseColor("#55000000"));

        text_paint = new Paint();
        text_paint.setColor(textColor);
        text_paint.setAntiAlias(true);
        text_paint.setTextSize(widthsize / 7.25f);
        text_paint.setFakeBoldText(true);
        text_paint.setFilterBitmap(true);
        text_paint.setMaskFilter(blu);
        text_paint.setShadowLayer(9,13,13,Color.parseColor("#55000000"));

    }

}

 

attrs文件:

    <declare-styleable name="waterProgress">
        <attr name="bgColor" format="color"></attr>
        <attr name="textColor" format="color"></attr>
    </declare-styleable>

上用法:

    <com.example.xln_sideslipmenu.DripProgressView
        android:layout_width="150dp"
        android:layout_height="320dp"
        app:bgColor="#FFD700"
        app:textColor="#ffffff">
    </com.example.xln_sideslipmenu.DripProgressView>

 

然后在你的进度监听回调里设置进度 setProgress(float progress) 就ok了。

码云完整代码:https://gitee.com/CeMaBenTeng/three-custom-view-effects

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐