Android自定义View实现进度条动画 本文实例为大家分享了Android自定义View实现进度条动画的具体代码,供大家参考,具体内容如下 控件效果 原理: 控制代码/ /更新进度值 val mHandler = object : Handler() { override fun handleMessage(msg: Message?) {
本文实例为大家分享了Android自定义View实现进度条动画的具体代码,供大家参考,具体内容如下
控件效果
原理:
控制代码/
/更新进度值
val mHandler = object : Handler() {
override fun handleMessage(msg: Message?) {
progressView.setCurrentProgress(progress1.toFloat())
}
}
//开启动画,更新进度值
private fun progressAdd() {
isAnimate = true
progress1 = 0
Thread(Runnable {
while (isAnimate) {
Thread.sleep(random.nextInt(200).toLong())
progress1 += 1
mHandler.sendEmptyMessage(0)
}
}).start()
}
//停止动画
private fun progressReduce() {
isAnimate = false
}
控件源码:
public class ProgressView extends View {
//前景颜色
private int FIRST_COLOR = 0xffFEA711; // 0xff00574B;//
//背景颜色
private int SECOND_COLOR = 0xffFBE39C;
private int mSecondWidth;
private int mFirstWidth;
private int mHeight;
private int mSecondRadius;
private int mFirstRadius;
private int progressPadding = 30;
private float currentValue;
private int maxProgress = 100;
//画笔
private Paint paint;
private RectF rectF;
private Bitmap leafBitmap;
private int mLeafWidth;
private int mLeafHeight;
private List<Leaf> mLeafInfos;
public ProgressView(Context context) {
super(context, null);
}
public ProgressView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public ProgressView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setColor(FIRST_COLOR);
paint.setAntiAlias(true);
rectF = new RectF();
leafBitmap = BitmapFactory.decodeResource(context.getResources(), R.mipmap.icon_leaf);
mLeafWidth = leafBitmap.getWidth();
mLeafHeight = leafBitmap.getHeight();
Log.e("zhen", " mLeafWidth: " + mLeafWidth + " mLeafHeight: " + mLeafHeight);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mHeight = h;
//外围
mSecondWidth = w;
mSecondRadius = (int) ((mSecondWidth * 1f / 5) / 2);
//内部进度条
mFirstWidth = mSecondWidth - progressPadding - mSecondRadius;
mFirstRadius = mSecondRadius - progressPadding;
mLeafInfos = new LeafFactory(mFirstRadius - mLeafWidth, 6).generateLeafs();
Log.e("zhen", " mSecondWidth: " + mSecondWidth + " mHeight: " + mHeight +
" mSecondRadius: " + mSecondRadius + " mFirstWidth: " + mFirstWidth + " mFirstRadius: " + mFirstRadius);
}
public void setCurrentProgress(float currentProgress) {
Log.e("zhen", "currentProgress: " + currentProgress);
if (currentProgress > 100) return;
currentValue = currentProgress / maxProgress * mFirstWidth;
invalidate();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//画布移动
canvas.translate(mSecondRadius, mHeight / 2);
//画背景左半圆
paint.setStyle(Paint.Style.FILL);
paint.setColor(SECOND_COLOR);
rectF.left = -mSecondRadius;
rectF.top = -mSecondRadius;
rectF.right = mSecondRadius;
rectF.bottom = mSecondRadius;
canvas.drawArc(rectF, 90, 180, false, paint);
//画背景右半圆
rectF.left = mSecondWidth - 3 * mSecondRadius;
rectF.top = -mSecondRadius;
rectF.right = mSecondWidth - mSecondRadius;
rectF.bottom = mSecondRadius;
canvas.drawArc(rectF, -90, 180, false, paint);
//画背景中间方形
rectF.left = 0;
rectF.top = -mSecondRadius;
rectF.right = mSecondWidth - 2 * mSecondRadius;
rectF.bottom = mSecondRadius;
canvas.drawRect(rectF, paint);
//绘制进度条半圆
paint.setColor(FIRST_COLOR);
float leftValue = (mFirstRadius - currentValue) > 0 ? (mFirstRadius - currentValue) : 0;
float angel = (float) Math.toDegrees(Math.acos(leftValue / mFirstRadius));
rectF.left = -mFirstRadius;
rectF.top = -mFirstRadius;
rectF.right = mFirstRadius;
rectF.bottom = mFirstRadius;
canvas.drawArc(rectF, 180 - angel, 2 * angel, false, paint);
//绘制进度条方形
if (currentValue >= mFirstRadius) {
currentValue = currentValue > mFirstWidth ? mFirstWidth : currentValue;
rectF.left = 0;
rectF.top = -mFirstRadius;
rectF.right = currentValue - mFirstRadius;
rectF.bottom = mFirstRadius;
canvas.drawRect(rectF, paint);
}
//落叶纷飞
if (currentValue > 0 && currentValue < mFirstWidth) {
long currentTime = System.currentTimeMillis();
for (int i = 0; i < mLeafInfos.size(); i++) {
Leaf leaf = mLeafInfos.get(i);
int delay = (int) ((currentTime - leaf.startTime) % CIRCLE_TIME);
leaf.x = mFirstWidth - mFirstRadius - delay * (mFirstWidth * 1f / CIRCLE_TIME);
if (leaf.x + mFirstRadius + mLeafWidth < currentValue) continue;
leaf.y = (float) (leaf.amplitude * Math.sin(2 * Math.PI / CIRCLE_TIME * delay + leaf.phaseOffeset));
Log.e("zhen", "延时ms数" + delay + " 角速度: " + (2 * Math.PI / CIRCLE_TIME) + " leaf.x: " + leaf.x + " leaf.y: " + leaf.y);
// 通过Matrix控制叶子旋转
Matrix matrix = new Matrix();
matrix.postTranslate(leaf.x, leaf.y);
// 根据叶子旋转方向确定叶子旋转角度
float rotate = leaf.rotateOrientation ? leaf.x % 360f : -leaf.x % 360;
matrix.postRotate(rotate, leaf.x + mLeafWidth / 2, leaf.y + mLeafHeight / 2);
Log.e("zhen", "落叶子旋转角度: " + rotate);
canvas.drawBitmap(leafBitmap, matrix, paint);
}
}
//绘制旋转风车
paint.setColor(Color.WHITE);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(10);
float x = mSecondWidth - 2 * mSecondRadius;
float y = 0;
canvas.drawCircle(x, y, mSecondRadius, paint);
paint.setStyle(Paint.Style.FILL);
paint.setColor(0XFFFCD158);
canvas.drawCircle(x, y, mSecondRadius - 5, paint);
}
@IntDef({Amplitude.SMALL, Amplitude.MIDDLE, Amplitude.LARGE})
public @interface Amplitude {
int SMALL = 0;
int MIDDLE = 1;
int LARGE = 2;
}
public static class Leaf {
public static long CIRCLE_TIME = 3000; //一个周期所需要的时间
//振幅大小
private int amplitude;
//初始相位偏移
private int phaseOffeset;
//旋转方向
private boolean rotateOrientation;
//延时时间
private long startTime;
//x位置取决于初始位置偏移
private float x;
//y位置取决于振幅,初始相位
private float y;
@Override
public String toString() {
return "Leaf{" +
"amplitude=" + amplitude +
", phaseOffeset=" + phaseOffeset +
", rotateOrientation=" + rotateOrientation +
", startTime=" + startTime +
", x=" + x +
", y=" + y +
'}';
}
}
public static class LeafFactory {
private Random random = new Random();
int randomValue;
private int mHeight;
private int mLeafSize;
public LeafFactory(int mHeight, int mLeafSize) {
this.mHeight = mHeight;
this.mLeafSize = mLeafSize;
}
public List<Leaf> generateLeafs() {
List<Leaf> mLeafsInfo = new ArrayList<>();
for (int i = 0; i < mLeafSize; i++) {
mLeafsInfo.add(generateLeaf());
}
return mLeafsInfo;
}
private Leaf generateLeaf() {
Leaf leaf = new Leaf();
randomValue = random.nextInt(3);
switch (randomValue) {
case Amplitude.SMALL:
leaf.amplitude = (int) (mHeight * 1f / 3);
break;
case Amplitude.MIDDLE:
leaf.amplitude = (int) (mHeight * 2f / 3);
break;
case Amplitude.LARGE:
leaf.amplitude = (int) (mHeight * 3f / 3);
break;
}
leaf.startTime = random.nextInt((int) CIRCLE_TIME);
leaf.phaseOffeset = random.nextInt(8);
leaf.rotateOrientation = random.nextBoolean();
Log.e("zhen", "生成一个叶子:" + leaf);
return leaf;
}
}
}
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。
沃梦达教程
本文标题为:Android自定义View实现进度条动画
基础教程推荐
猜你喜欢
- Flutter进阶之实现动画效果(三) 2022-10-28
- iOS开发使用XML解析网络数据 2022-11-12
- Android Compose自定义TextField实现自定义的输入框 2023-05-13
- Android实现短信验证码输入框 2023-04-29
- iOS中如何判断当前网络环境是2G/3G/4G/5G/WiFi 2023-06-18
- iOS开发 全机型适配解决方法 2023-01-14
- IOS获取系统相册中照片的示例代码 2023-01-03
- Android开发Compose集成高德地图实例 2023-06-15
- MVVMLight项目Model View结构及全局视图模型注入器 2023-05-07
- iOS Crash常规跟踪方法及Bugly集成运用详细介绍 2023-01-18