如图所示:

自定义属性:

在values下创建attrs.xml 文件

<?xml version="1.0" encoding="utf-8"?>
<resources> <declare-styleable name="WaveProgressView">
<attr name="radius" format="dimension|reference" />
<attr name="radius_color" format="color|reference" />
<attr name="progress_text_color" format="color|reference" />
<attr name="progress_text_size" format="dimension|reference" />
<attr name="progress_color" format="color|reference" />
<attr name="progress" format="float" />
<attr name="maxProgress" format="float" />
</declare-styleable> </resources>

 样式 styles.xml 中

<style name="WaveProgressViewDefault">
<item name="radius">55dp</item>
<item name="progress_text_color">#fff</item>
<item name="progress_text_size">20sp</item>
<item name="progress_color">#C215AB30</item>
<item name="radius_color">#FF734B58</item>
<item name="progress">0</item>
<item name="maxProgress">100</item>
</style>

自定义view

package com.chuanye.shuiqiudemo1;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View; import java.text.DecimalFormat; public class WaveProgressView extends View { private int radius = dp2px(55);//半径
private int textColor;//进度字体颜色
private int textSize;//进度字体大小
private int progressColor;//进度颜色
private int radiusColor;
private Paint textPaint;
private Paint circlePaint;
private Paint pathPaint;
private Bitmap bitmap;
private Canvas bitmapCanvas;
private int width = 10, height = 10;
private int minPadding;
private float progress;//当前进度
private float maxProgress;//最大进度
private Path path = new Path();
private DecimalFormat df = new DecimalFormat("0.0"); public WaveProgressView(Context context) {
this(context, null);
} public WaveProgressView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
} public WaveProgressView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.WaveProgressView, defStyleAttr, R.style.WaveProgressViewDefault);
radius = (int) a.getDimension(R.styleable.WaveProgressView_radius, radius);//半径
textColor = a.getColor(R.styleable.WaveProgressView_progress_text_color, 0);//进度字体颜色
textSize = a.getDimensionPixelSize(R.styleable.WaveProgressView_progress_text_size, 0);//进度字体大小
progressColor = a.getColor(R.styleable.WaveProgressView_progress_color, 0);//进度颜色
radiusColor = a.getColor(R.styleable.WaveProgressView_radius_color, 0);//半径颜色
progress = a.getFloat(R.styleable.WaveProgressView_progress, 0);//当前进度
maxProgress = a.getFloat(R.styleable.WaveProgressView_maxProgress, 100);//最大进度
a.recycle();//回收利用 //初始化一些画笔 文本画笔
textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
textPaint.setTextSize(textSize);
textPaint.setColor(textColor);
textPaint.setDither(true); //圆 画笔
circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
circlePaint.setColor(radiusColor);
circlePaint.setDither(true); //道路 进度画笔
pathPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
pathPaint.setColor(progressColor);
pathPaint.setDither(true);
//设置转送模式
pathPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
} @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//计算宽和高
int exceptW = getPaddingLeft() + getPaddingRight() + 2 * radius;
int exceptH = getPaddingTop() + getPaddingBottom() + 2 * radius;
int width = resolveSize(exceptW, widthMeasureSpec);
int height = resolveSize(exceptH, heightMeasureSpec);
int min = Math.min(width, height); this.width = this.height = min; //计算半径,减去padding的最小值
int minLR = Math.min(getPaddingLeft(), getPaddingRight());
int minTB = Math.min(getPaddingTop(), getPaddingBottom());
minPadding = Math.min(minLR, minTB);
radius = (min - minPadding * 2) / 2; setMeasuredDimension(min, min);
} @Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (bitmap == null) {
bitmap = Bitmap.createBitmap(this.width, this.height, Bitmap.Config.ARGB_8888);
bitmapCanvas = new Canvas(bitmap);
}
bitmapCanvas.save();
//移动坐标系 转化画布
bitmapCanvas.translate(minPadding, minPadding);
//绘制圆
bitmapCanvas.drawCircle(radius, radius, radius, circlePaint); //绘制PATH
//重置绘制路线
path.reset();
float percent = progress * 1.0f / maxProgress;
float y = (1 - percent) * radius * 2;
//移动到右上边
path.moveTo(radius * 2, y);
//移动到最右下方
path.lineTo(radius * 2, radius * 2);
//移动到最左下边
path.lineTo(0, radius * 2);
//移动到左上边
// path.lineTo(0, y);
//实现左右波动,根据progress来平移
path.lineTo(-(1 - percent) * radius * 2, y);
if (progress != 0.0f) {
//根据直径计算绘制贝赛尔曲线的次数
int count = radius * 4 / 60;
//控制-控制点y的坐标
float point = (1 - percent) * 15;
for (int i = 0; i < count; i++) {
path.rQuadTo(15, -point, 30, 0);
path.rQuadTo(15, point, 30, 0);
}
}
//闭合
path.close();
bitmapCanvas.drawPath(path, pathPaint); //绘制文字
String text = progress + "%";
float textW = textPaint.measureText(text);
Paint.FontMetrics fontMetrics = textPaint.getFontMetrics();
float baseLine = radius - (fontMetrics.ascent + fontMetrics.descent) / 2;
bitmapCanvas.drawText(text, radius - textW / 2, baseLine, textPaint); bitmapCanvas.restore(); canvas.drawBitmap(bitmap, 0, 0, null);
} public float getProgress() {
return progress;
} public void setProgress(float progress) {
this.progress = Float.valueOf(df.format(progress));
invalidate();
} private int dp2px(int dp) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics());
} private final static class SavedState extends BaseSavedState {
float progress; public SavedState(Parcel source) {
super(source);
} public SavedState(Parcelable superState) {
super(superState);
} public static final Parcelable.Creator<SavedState> CREATOR
= new Parcelable.Creator<SavedState>() {
public SavedState createFromParcel(Parcel in) {
return new SavedState(in);
} public SavedState[] newArray(int size) {
return new SavedState[size];
}
};
} @Override
protected Parcelable onSaveInstanceState() {
Parcelable superState = super.onSaveInstanceState();
SavedState ss = new SavedState(superState);
ss.progress = progress;
return ss;
} @Override
protected void onRestoreInstanceState(Parcelable state) {
SavedState ss = (SavedState) state;
super.onRestoreInstanceState(ss.getSuperState());
setProgress(ss.progress);
} }

布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:wpv="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center_horizontal"> <Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/btn_main3"
android:text="开启"
android:onClick="start"
tools:ignore="OnClick" /> <com.chuanye.shuiqiudemo1.WaveProgressView
android:id="@+id/wpv_0"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
wpv:progress="15" /> <com.chuanye.shuiqiudemo1.WaveProgressView
android:id="@+id/wpv_1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
wpv:maxProgress="80"
wpv:progress_color="#dd65A6DA"
wpv:progress_text_color="@color/colorAccent"
wpv:progress_text_size="20sp"
wpv:radius="60dp"
wpv:radius_color="#AAffdd33" /> <com.chuanye.shuiqiudemo1.WaveProgressView
android:id="@+id/wpv_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
wpv:maxProgress="120"
wpv:progress_color="#DC7E2040"
wpv:progress_text_size="13sp"
wpv:radius="70dp"
wpv:radius_color="#7F6B1AB3" /> <Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/btn_main32"
android:text="设置值" />
</LinearLayout>

MainActivity 中

package com.chuanye.shuiqiudemo1;

import android.animation.ObjectAnimator;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.BounceInterpolator;
import android.view.animation.LinearInterpolator;
import android.widget.Button; public class Main3Activity extends AppCompatActivity {
//https://blog.csdn.net/ta893115871/article/details/52245815/
//private WaveProgressView waveProgressView_0;
private String TAG = "Main3Activity";
//private WaveProgressView waveProgressView_1;
//private WaveProgressView waveProgressView_2;
private WaveProgressView waveProgressView_0, waveProgressView_1, waveProgressView_2; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main3); Log.i(TAG,"onCreate..."); waveProgressView_0 = (WaveProgressView) findViewById(R.id.wpv_0); waveProgressView_1 = (WaveProgressView) findViewById(R.id.wpv_1);
waveProgressView_2 = (WaveProgressView) findViewById(R.id.wpv_2); Button btn_main32 = findViewById(R.id.btn_main32);
btn_main32.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
waveProgressView_0.setProgress(85);
}
}); } public void start(View view) {
ObjectAnimator objectAnimator0 = ObjectAnimator.ofFloat(waveProgressView_0, "progress", 0f, 100f);
objectAnimator0.setDuration(3300);
objectAnimator0.setInterpolator(new LinearInterpolator());
objectAnimator0.start(); ObjectAnimator objectAnimator1 = ObjectAnimator.ofFloat(waveProgressView_1, "progress", 0f, 80f);
objectAnimator1.setDuration(3000);
objectAnimator1.setInterpolator(new AccelerateInterpolator());
objectAnimator1.start(); ObjectAnimator objectAnimator2 = ObjectAnimator.ofFloat(waveProgressView_2, "progress", 0f, 120f);
objectAnimator2.setDuration(5000);
objectAnimator2.setInterpolator(new BounceInterpolator());
objectAnimator2.start();
}
}

完成

最新文章

  1. PropertiesFactoryBean PropertyPlaceholderConfigurer 区别
  2. git branch用法总结
  3. 使用bower管理前端依赖
  4. How to set China Azure Storage Connection String
  5. Oracle 12c 数据库中scott用户不存在的解决方法
  6. jQuery live与bind的区别
  7. HW2.2
  8. Quartz1.8.5例子(七)
  9. 飘逸的python - 两种with语句实现方法
  10. 解决中文乱码( jsp表单提交中文时出现乱码)
  11. social relation &amp; recommender system
  12. selenium+python
  13. 考了3年,工作四年,零基础在职终于拿到CFA证书
  14. Nginx干货(一)隐藏Nginx标识与版本号
  15. bzoj 3192: [JLOI2013]删除物品
  16. intellij idea maven 工程生成可执行的jar
  17. Nginx 常见问题
  18. RMQ求LCA
  19. Windows Socket 编程_单个服务器对多个客户端简单通讯
  20. 该 URL“XX”无效。它可能指向不存在的文件或文件夹,或者是指向不在当前网站中的有效文件或文件夹

热门文章

  1. Comet OJ 夏季欢乐赛 篮球校赛
  2. jQyery简史和下载引用方法
  3. TypeScript 解构和展开
  4. python 识别二维码内容的方法
  5. 安装PyInstaller失败
  6. 渗透测试工具Nmap篇
  7. Spring Boot 知识笔记(servlet、监听器、拦截器)
  8. 出现Strict Standards: Only variables should be passed by reference in的解决方法
  9. IO流—其他流
  10. 【mysql】搜索带\字符