<android>水滴效果的进度条 DripProgressView(二阶贝塞尔曲线自定义view)

本文介绍了一款使用二阶贝塞尔曲线实现的水滴效果进度条,提供了设置进度和重置的功能,并附带了完整的代码实现。通过自定义View,作者实现了动画效果,包括水滴下落和文字跟随下落的动态展示。同时,提供了attrs文件以自定义背景颜色和文字颜色。代码已在码云上开源。
摘要由CSDN通过智能技术生成

  最近写了一个水滴效果的进度条,加了点特效,就是个简单的自定义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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值