Android 属性动画+自定义view实现加载动画
2020-01-21 本文已影响0人
Levipeng
如图
splash.gif
思路分析
过程拆分
1.画6个小圆圈
2.小圆圈转动起来
3.小圆圈聚合
4.开始扩散
首先确定6个圆的坐标,画出小圆,圆要转动,就是要同步改变每个小圆的坐标,小圆的运动轨迹是个圆。所以使用属性动画,属性动画的变化区别设置为0-2π,然后使用勾股定律求出旋转的圆心坐标,重绘。就能实现旋转效果了。然后只要改变这个大圆的半径就能实现聚合效果。最后扩散效果这个思路就很sao,就是画一个圆,画笔的style设置成STROKE,只要改变Stroke的宽度就行了。是不是很简单。
思路都有了开始撸码
public class SplashView extends View {
//小圆半径
private int smallCircleRadius = 20;
//大圆半径
private int bigCircleRadius = 100;
//小圆画笔
private Paint mPaintSmallCircle;
//小圆颜色
private int[] colorsCircle;
//小圆之间的角度
private float angle;
//属性动画旋转角度
private float scaleAngle;
//属性动画变化半径
private int scaleRadiu;
private SlpashState drawState;
//屏幕对角线的一半
private float expandRadius;
//扩散画笔
private Paint mPaintExpand;
private float mPaintExpandMove;
public SplashView(Context context) {
this(context, null);
}
public SplashView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init(context);
}
private void init(Context context) {
colorsCircle = context.getResources().getIntArray(R.array.colorCircle);
mPaintSmallCircle = new Paint();
mPaintSmallCircle.setAntiAlias(true);
mPaintSmallCircle.setStyle(Paint.Style.FILL);
mPaintExpand=new Paint();
mPaintExpand.setAntiAlias(true);
mPaintExpand.setStyle(Paint.Style.STROKE);
mPaintExpand.setColor(Color.WHITE);
angle = (float) (2 * Math.PI / colorsCircle.length);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
expandRadius= (float) Math.sqrt(w*w+h*h)/2;
}
public void cancle() {
if (drawState instanceof RotateState){
//((RotateState)drawState).cancle();
drawState=new MergingState();
}
}
//使用策略模式
private abstract class SlpashState {
public abstract void drawState(Canvas canvas);
}
//旋转状态
private class RotateState extends SlpashState {
private ValueAnimator valueAnimator;
public RotateState() {
valueAnimator = ValueAnimator.ofFloat(0f, (float) Math.PI * 2);
valueAnimator.setDuration(2000);
//线性变换插值器
valueAnimator.setInterpolator(new LinearInterpolator());
valueAnimator.setRepeatCount(ValueAnimator.INFINITE);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
scaleAngle = (float) animation.getAnimatedValue();
postInvalidate();
}
});
valueAnimator.start();
}
public void cancle() {
valueAnimator.cancel();
}
@Override
public void drawState(Canvas canvas) {
//绘制背景
drawBackground(canvas);
//绘制圆
drawCircle(canvas);
}
}
//聚合状态
private class MergingState extends SlpashState {
public MergingState() {
ValueAnimator valueAnimator = ValueAnimator.ofInt(bigCircleRadius, smallCircleRadius);
valueAnimator.setDuration(1000);
//线性变换插值器
valueAnimator.setInterpolator(new LinearInterpolator());
valueAnimator.setRepeatCount(0);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
bigCircleRadius = (int) animation.getAnimatedValue();
postInvalidate();
}
});
valueAnimator.start();
valueAnimator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
//开始扩散
drawState=new ExpandState();
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
}
@Override
public void drawState(Canvas canvas) {
//绘制背景
drawBackground(canvas);
//绘制圆
drawCircle(canvas);
}
}
//扩散状态
private class ExpandState extends SlpashState {
private ValueAnimator valueAnimator;
public ExpandState() {
valueAnimator = ValueAnimator.ofFloat(0,expandRadius);
valueAnimator.setDuration(2000);
//线性变换插值器
valueAnimator.setInterpolator(new LinearInterpolator());
valueAnimator.setRepeatCount(0);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mPaintExpandMove = (float) animation.getAnimatedValue();
postInvalidate();
}
});
valueAnimator.start();
}
public void cancle() {
valueAnimator.cancel();
}
@Override
public void drawState(Canvas canvas) {
//绘制背景
drawBackground(canvas);
//绘制圆
// drawCircle(canvas);
}
}
private void drawCircle(Canvas canvas) {
for (int i = 0; i < colorsCircle.length; i++) {
//绘制每个小圆
mPaintSmallCircle.setColor(colorsCircle[i]);
//根据勾股定理求出xy的坐标
float cx = (float) Math.cos(i * angle + scaleAngle) * bigCircleRadius + getWidth() / 2;
float cy = (float) Math.sin(i * angle + scaleAngle) * bigCircleRadius + getHeight() / 2;
canvas.drawCircle(cx, cy, smallCircleRadius, mPaintSmallCircle);
}
}
private void drawBackground(Canvas canvas) {
if (drawState instanceof ExpandState){
Log.d("mPaintExpandMove ",mPaintExpandMove+"");
//画笔的宽度=对角线宽度-空心圆的半径
float strokeWidth=expandRadius-mPaintExpandMove;
mPaintExpand.setStrokeWidth(strokeWidth);
//画圆的半径=空心圆的半径+画笔宽度/2
float radius = mPaintExpandMove + strokeWidth/2;
canvas.drawCircle(getWidth()/2,getHeight()/2,radius,mPaintExpand);
}else{
canvas.drawColor(Color.WHITE);
}
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (drawState == null) {
drawState = new RotateState();
}
drawState.drawState(canvas);
}
}