您的位置:首页 > 其它

自定义电池充电动画

2017-10-28 10:01 190 查看
最近公司项目涉及到一个电池充电的效果,需要电量从底部上顶部逐渐变多,再变为0。反复循环。在借鉴了别人写的动画后,自己写了如下动画。里面有些代码是写死的,诸君可以自行修改。效果如下:



话不多说,开始贴代码

1、attrs。这是自定义view必须的。

<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="charging_progress">
<!--item个数-->
<attr name="cgv_item_count" format="integer" />
<!--方向-->
<attr name="cgv_oritation" format="integer" />
<!--动画时长-->
<attr name="cgv_duration" format="integer" />
<!--边界宽度-->
<attr name="cgv_border_width" format="dimension" />
<!--边界颜色-->
<attr name="cgv_border_color" format="color" />
<!--圆角半径-->
<attr name="cgv_border_cornor_radius" format="dimension" />
<!--充电内模块的宽度-->
<attr name="cgv_item_width" format="dimension" />
<!--充电内模块的高度-->
<attr name="cgv_item_height" format="dimension" />
<!--充电内模块的前景色,充电中的颜色-->
<attr name="cgv_item_charging_src" format="color" />
<!--充电内模块的背景色,未充电的颜色-->
<attr name="cgv_item_charging_background" format="color" />
<!--view 的背景-->
<attr name=<
13327
/span>"cgv_background" format="color" />
</declare-styleable>
</resources>
2、在xml进行引用
<com.example.batteryanim.ChargingProgess
android:id="@+id/chargingprigressView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:cgv_item_count="1000"
app:cgv_item_height="0.2dp"
app:cgv_item_width="100dp"
app:cgv_item_charging_src="#00A1BD"
app:cgv_item_charging_background="#000000"
app:cgv_background="#F9F9F9"
app:cgv_border_width="4dp"
app:cgv_border_color="#00A1BD"/>
/>
3、最重要的一个就是自定义这个view
package com.example.batteryanim;

import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.View;
import android.view.animation.LinearInterpolator;

/**
* 充电进度绘制,使用属性动画完成。
*/
public class ChargingProgess extends View {

private Context mContext;
private Paint mPaint;//外部矩形以及内部充电动画画笔
private Paint mPaintTop;//顶部矩形
private static final int VERTICAL = 0;//竖直方向
private int oritation;//view的方向
private float border_width;//边界宽度
private int item_count;//item个数
private float item_width;//item宽度
private float item_height;//item高度
private int item_charging_src;//view内部的进度前景色
private int item_charging_background;//view内部的进度背景色
private int background;//view背景色
private int border_color; //边界颜色
private float border_cornor_radius; //圆角半径
private int duration;//动画时间
private int mWidth;//整个view的宽度
private int mHeight;//整个view的高度
public static final int AC = 2;
private int chargeType = AC;//充电类型,默认为交流
private int progress = 0;
private ValueAnimator animAC;
private int mCurrPro = 0;
private int mTopRectHigh;//顶部进度条的高度
private int mRect = 50;
private int mWidthRate = 20;

public ChargingProgess(Context context) {
this(context, null);
}

public ChargingProgess(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}

public ChargingProgess(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.mContext = context;
getSettingValue(attrs);
initView(context);
}

/**
* 获取在xml中设置的属性值
*
* @param attrs
*/
private void getSettingValue(AttributeSet attrs) {
TypedArray array = mContext.obtainStyledAttributes(attrs, com.example.batteryanim.R.styleable.charging_progress);
oritation = array.getInt(com.example.batteryanim.R.styleable.charging_progress_cgv_oritation, VERTICAL);
border_width = array.getDimension(com.example.batteryanim.R.styleable.charging_progress_cgv_border_width, dp2px(2));
item_height = array.getDimension(com.example.batteryanim.R.styleable.charging_progress_cgv_item_height, dp2px(10));
item_width = array.getDimension(com.example.batteryanim.R.styleable.charging_progress_cgv_item_width, dp2px(20));
item_charging_src = array.getColor(com.example.batteryanim.R.styleable.charging_progress_cgv_item_charging_src, 0xffffea00);
item_charging_background = array.getColor(com.example.batteryanim.R.styleable.charging_progress_cgv_item_charging_background, 0xff544645);
background = array.getColor(com.example.batteryanim.R.styleable.charging_progress_cgv_background, 0xff463938);
border_color = array.getColor(com.example.batteryanim.R.styleable.charging_progress_cgv_border_color, 0xffb49d7c);
border_cornor_radius = array.getDimension(com.example.batteryanim.R.styleable.charging_progress_cgv_border_cornor_radius, dp2px(2));
duration = array.getInt(com.example.batteryanim.R.styleable.charging_progress_cgv_duration, 10 * 1000);
item_count = array.getInt(com.example.batteryanim.R.styleable.charging_progress_cgv_item_count, 100);
}

/**
* 初始化两种画笔
* @param context
*/
private void initView(Context context) {
mPaint = new Paint();
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(border_width);
mPaint.setColor((border_color));

mPaintTop = new Paint();
mPaintTop.setStyle(Paint.Style.FILL);
mPaintTop.setStrokeWidth(border_width);
mPaintTop.setColor(border_color);
}

/**
* 当前进度
* @return
*/
public int getProgress() {
return progress % 100;
}

/**
* 设置充电进度
* @param progress
*/
public void setProgress(int progress) {
this.progress = progress;
invalidate();
}

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//顶部矩形的宽高
int left = mWidth * 3 / 8;
int top = 0;
int right = 5 * mWidth / 8;
int bottom = (int) (item_height *60);
mTopRectHigh = bottom - top;

//顶部的矩形
RectF topRect = new RectF(left, top, right, bottom);
canvas.drawRoundRect(topRect, border_cornor_radius, border_cornor_radius, mPaintTop);

//大矩形。宽高分别是指最大view的宽高
RectF border = new RectF(0 + 5, bottom + 5, mWidth - 5, mHeight - 5);
canvas.drawRoundRect(border, mRect, mRect, mPaint);
drawACAnimaiton(canvas);

//因为每次刷新都要走onDraw方法,所以之前在drawACAnimaiton设置了画笔,现在要还原
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(border_width);
mPaint.setColor((border_color));
}

/**
* 关闭动画
*/
public void closeAnimation() {
progress = 0;
invalidate();
if (animAC != null) {
animAC.cancel();
}
}

/**
* 设置交流动画,属性动画
*/
public void setACAnimation() {
chargeType = AC;
animAC = ValueAnimator.ofInt(0, 1000);
animAC.setDuration(10000);
animAC.setInterpolator(new LinearInterpolator());
animAC.setRepeatCount(ValueAnimator.INFINITE);
animAC.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mCurrPro = (Integer) animation.getAnimatedValue();
Log.i("liwei", "mCurrPro:" + mCurrPro);
invalidate();
}
});
animAC.start();
}

/**
* 绘制交流动画的具体走向
* @param canvas
*/
private void drawACAnimaiton(Canvas canvas) {
RectF backRect = null;
//设置从30到970是因为顶部一些地方和底部一些距离要留空白
for (int i = 30; i <= mCurrPro && i <= 970; i++) {
//这里的宽并没有严格按照比例来,而是自己看界面随意调的,mWidthRate也就没有什么含义
float left = mWidth / (mWidthRate + 2) + mWidth * 1 / 50;
//将View里面最下面的矩形是分为1000份的
float top = mHeight - i * item_height;
float right = (mWidthRate + 1) * mWidth / (mWidthRate + 2) - mWidth * 1 / 50;
float bottom = top + item_height;

//这是为顶部和底部的动画准备的,顶部和底部的动画样子和中间部分不同
int bottomDis=60;
int topDis=940;
int timeRate=1;

//最底部动画样子
if (i<bottomDis){
//动画呈现线性
int j=bottomDis-i;
//这里的宽度和中间部分不同
left = mWidth / (mWidthRate + 2) + mWidth * 1 / 50+j*timeRate;
right = (mWidthRate + 1) * mWidth / (mWidthRate + 2) - mWidth * 1 / 50-j*timeRate;
backRect = new RectF(left, top, right, bottom);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setColor(item_charging_src);
canvas.drawRect(backRect, mPaint);
}else if (i>topDis){
//最顶部动画样子
//这里的宽度和中间部分不同
//动画呈现线性
int j=i-topDis;
left = mWidth / (mWidthRate + 2) + mWidth * 1 / 50+j*timeRate;
right = (mWidthRate + 1) * mWidth / (mWidthRate + 2) - mWidth * 1 / 50-j*timeRate;
backRect = new RectF(left, top, right, bottom);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setColor(item_charging_src);
canvas.drawRect(backRect, mPaint);
}else if (i==200||i==400||i==600||i==800){
//这边的判断是为了中间动画的空白
backRect = new RectF(left, top, right, bottom);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setColor(Color.WHITE);
canvas.drawRect(backRect, mPaint);
} else{
//中间动画
backRect = new RectF(left, top, right, bottom);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setColor(item_charging_src);
canvas.drawRect(backRect, mPaint);
}
}
}

/**
* 测量view的宽和高
* @param widthMeasureSpec
* @param heightMeasureSpec
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//高度等于中间的矩形高度+最顶部的一个小矩形
mHeight = (int) (item_count * item_height + item_height * 60);
Log.i("liwei", "mHeight:" + mHeight);
mWidth = (int) ((mWidthRate + 2) * item_width / mWidthRate);
setMeasuredDimension(mWidth, mHeight);
}

/**
* dp转化为px`
*
* @param dp
* @return
*/
protected int dp2px(int dp) {
return (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
dp,
getResources().getDisplayMetrics());
}

/**
* sp转为px
*
* @param sp
* @return
*/
protected int sp2px(int sp) {
return (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_SP,
sp,
getResources().getDisplayMetrics());
}
}
项目下载链接在这里,有建议的也可以在评论里告诉我 http://download.csdn.net/download/qq_25330791/10042581  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: