如图所示:

自定义属性:

在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();
}
}

完成

Android中自定义水球的更多相关文章

  1. [转]Android中自定义checkbox样式

    android中自定义checkbox的图片和大小   其实很简单,分三步: 1.在drawable中创建文件checkbox_selector.xml: <?xml version=" ...

  2. 转--Android中自定义字体的实现方法

    1.Android系统默认支持三种字体,分别为:“sans”, “serif”, “monospace 2.在Android中可以引入其他字体 . 复制代码 代码如下: <?xml versio ...

  3. Android中自定义ActionBar的背景色等样式style

    Android中想要去自定义ActionBar的背景色等样式. [折腾过程] 1.自己找代码,发现对应的配置的地方了: AndroidManifest.xml ? 1 2 <applicatio ...

  4. Android中自定义veiw使用Java中的回调方法

    //------------------MainActivity----中---------------------------------- import android.os.Bundle;imp ...

  5. android开发:Android 中自定义View的应用

    大家好我们今天的教程是在Android 教程中自定义View 的学习,对于初学着来说,他们习惯了Android 传统的页面布局方式,如下代码: <?xml version="1.0&q ...

  6. Android中自定义组合控件

    Android中自定义控件的情况非常多,一般自定义控件可以分为两种:继承控件及组合控件.前者是通过继承View或其子类,重写方法实现自定义的显示及事件处理方式:后者是通过组合已有的控件,来实现结构的简 ...

  7. Android中自定义ListView实现上拉加载更多和下拉刷新

    ListView是Android中一个功能强大而且很常用的控件,在很多App中都有ListView的下拉刷新数据和上拉加载更多这个功能.这里我就简单记录一下实现过程. 实现这个功能的方法不止一个,Gi ...

  8. Android中自定义View和自定义动画

    Android FrameWork 层给我们提供了很多界面组件,但是在实际的商业开发中这些组件往往并不能完全满足我们的需求,这时候我们就需要自定义我们自己的视图和动画. 我们要重写系统的View就必须 ...

  9. Android中自定义IP控件

    最近在搞Android项目,之前并没有系统的去学过这方面的编程,只能边看书边撸代码.在项目的开发的过程中,需要一个IP控件,后面了解到Android中并没有这样的控件,于是网上搜索,发现得到的结果并不 ...

随机推荐

  1. PAC、KNN和GridSearchCV

    PCA PCA主要是用来数据降维,将高纬度的特征映射到低维度,具体可学习线性代数. 这里,我们使用sklearn中的PCA. from sklearn.decomposition import PCA ...

  2. 【oracle】decode函数

    DECODE(参数,值1,翻译值1,值2,翻译值2,...值n,翻译值n,缺省值) 值1:当参数=值1    翻译值1:想要得到的值 值2:当参数=值2 翻译值2:想要得到的值

  3. axios二次封装

    import axios from "axios" //请求拦截器 axios.interceptors.request.use(function (config) { retur ...

  4. SyntaxError: Non-ASCII character ‘\xe5’ in file 的解决办法

    在Python脚本中包含中文的时候,会遇到编码错误.例如: 出现SyntaxError: Non-ASCII character ‘\xe5’ in file 的错误. 解决办法:是因为编码有问题,所 ...

  5. struts2.xml 中result type属性说明

    chain           用来处理Action链,被跳转的action中仍能获取上个页面的值,如request信息.           com.opensymphony.xwork2.Acti ...

  6. PG数据库CPU和内存满负荷运转优化案

    1.问题描述 某客户系统采用三层架构:数据库—应用服务—前端应用.其中数据库使用PostgreSQL 10.0作为数据库软件.自周四起,服务器的CPU与内存使用率持续处于过饱合状态,并因此导致了数次宕 ...

  7. C的位运算符

    1.前言 C的位运算符有&(按位与).|(按位或).^(按位异或).~(按位取反),位运算符把运算对象看作是由二进制位组成的位串信息,按位完成指定的运算,得到相应的结果. 2.位运算符 在上面 ...

  8. 设置KAFKA

    让我们继续下载并设置Kafka,启动zookeeper,集群,生产者和消费者.   要下载Kafka,请参阅此链接  http://kafka.apache.org/downloads.html 下载 ...

  9. jupyter lab matplotlib 画图

    解决jupyter lab   plt.plot()  不画图的问题 import matplotlib.pyplot as plt %matplotlib inline #insert this c ...

  10. B树和B+树的增/删结点(转)

    add by zhj: 算法其实不复杂,尤其是增加结点的算法,逻辑很简单,但有时自己想不到. 增加结点算法:首先,对于B树,没有重复结点,所以新插入的数据一定会落在叶结点上,或者说落在叶结点的所有父结 ...