Android中自定义水球
如图所示:
自定义属性:
在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中自定义水球的更多相关文章
- [转]Android中自定义checkbox样式
android中自定义checkbox的图片和大小 其实很简单,分三步: 1.在drawable中创建文件checkbox_selector.xml: <?xml version=" ...
- 转--Android中自定义字体的实现方法
1.Android系统默认支持三种字体,分别为:“sans”, “serif”, “monospace 2.在Android中可以引入其他字体 . 复制代码 代码如下: <?xml versio ...
- Android中自定义ActionBar的背景色等样式style
Android中想要去自定义ActionBar的背景色等样式. [折腾过程] 1.自己找代码,发现对应的配置的地方了: AndroidManifest.xml ? 1 2 <applicatio ...
- Android中自定义veiw使用Java中的回调方法
//------------------MainActivity----中---------------------------------- import android.os.Bundle;imp ...
- android开发:Android 中自定义View的应用
大家好我们今天的教程是在Android 教程中自定义View 的学习,对于初学着来说,他们习惯了Android 传统的页面布局方式,如下代码: <?xml version="1.0&q ...
- Android中自定义组合控件
Android中自定义控件的情况非常多,一般自定义控件可以分为两种:继承控件及组合控件.前者是通过继承View或其子类,重写方法实现自定义的显示及事件处理方式:后者是通过组合已有的控件,来实现结构的简 ...
- Android中自定义ListView实现上拉加载更多和下拉刷新
ListView是Android中一个功能强大而且很常用的控件,在很多App中都有ListView的下拉刷新数据和上拉加载更多这个功能.这里我就简单记录一下实现过程. 实现这个功能的方法不止一个,Gi ...
- Android中自定义View和自定义动画
Android FrameWork 层给我们提供了很多界面组件,但是在实际的商业开发中这些组件往往并不能完全满足我们的需求,这时候我们就需要自定义我们自己的视图和动画. 我们要重写系统的View就必须 ...
- Android中自定义IP控件
最近在搞Android项目,之前并没有系统的去学过这方面的编程,只能边看书边撸代码.在项目的开发的过程中,需要一个IP控件,后面了解到Android中并没有这样的控件,于是网上搜索,发现得到的结果并不 ...
随机推荐
- Pandas | 14 统计函数
统计方法有助于理解和分析数据的行为.可以将这些统计函数应用到Pandas的对象上. pct_change()函数 系列,DatFrames和Panel都有pct_change()函数.此函数将每个元素 ...
- 二分查找java实现
二分查找也称折半查找(Binary Search),它是一种效率较高的查找方法.但是,折半查找要求线性表必须采用顺序存储结构,而且表中元素按关键字有序排列. 二分查找思路非常简单,由粗暴的遍历查找改为 ...
- Layui 关闭当前标签页
parent.layui.admin.events.closeThisTabs();
- contest4 CF1091 div2 ooooxx ooooxx ooooox
题意 div2E 一个有\(n+1\)个点的无向图, 给出\(n\)个点的度数, 求出每一种可能的\(n+1\)的度数 (题面附带公式 graph realization problem)
- 【转】Go 内存管理
1. 前言 编写过C语言程序的肯定知道通过malloc()方法动态申请内存,其中内存分配器使用的是glibc提供的ptmalloc2.除了glibc,业界比较出名的内存分配器有Google的tcmal ...
- 第03组 Beta冲刺(1/4)
队名:不等式方程组 组长博客 作业博客 团队项目进度 组员一:张逸杰(组长) 过去两天完成的任务: 文字/口头描述: 制定了初步的项目计划,并开始学习一些推荐.搜索类算法 GitHub签入纪录: 暂无 ...
- html中利用flex容器书写的布局样式
首先页面基本样式见下图: 如有兴趣可以打开https://migloo.gitee.io/front 或者 https://www.igloo.xin/front 进行查看
- Maven 教程(5)— Maven目录结构及常用命令说明
原文地址:https://blog.csdn.net/liupeifeng3514/article/details/79543159 1.Maven目录结构说明 Maven总体目录结构如下图: bin ...
- mysql 添加注释
给表添加注释: alter table m_tb100_disabledsoldier comment '残疾士兵'; 给表中的字段添加注释alter table m_tb100_disable ...
- 关于JavaSE程序的小总结(不分先后顺序 后续继续补充)
统计字符串中某个字符串出现的次数 package com.jiang.demo01; public class Demo01 { public static void main(String[] ar ...