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