GIF.gif
上面就是使用属性动画实现的一个加载效果;实现思路:
1、自定义view绘制三个小圆;
2、将绘制好的三个小圆添加到自定义的布局容器中;
3、给左边和右边的小圆设置动画,主要使用X轴的位移动画;
先进行第一步的实现,自定义view绘制三个小圆:
public class CircleView extends View {
private Paint mPaint;
//保存画笔的颜色
private int mColor;
public CircleView(Context context) {
this(context, null);
}
public CircleView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CircleView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
//初始化画笔
mPaint = new Paint();
//设置抗锯齿
mPaint.setAntiAlias(true);
//设置防抖动
mPaint.setDither(true);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//绘制圆形
int cx = getWidth() / 2;
int cy = getHeight() / 2;
canvas.drawCircle(cx, cy, cx, mPaint);
}
/**
* 切换颜色
*
* @param color
*/
public void exchangeColor(int color) {
mColor = color;
mPaint.setColor(color);
invalidate();
}
/**
* 获取当前颜色
*
* @return
*/
public int getColor() {
return mColor;
}
}
绘制小圆就是定义一个类 extends View 重写onDraw()方法,并调用canvas.drawCircle()方法进行圆的绘制;完成第一步接着实现第二步和三步;
public class LoadView extends RelativeLayout {
//三个小圆
private CircleView mLeftView, mMiddleView, mRightView;
//位移距离
private int MTRANSLATION_DISTANCE = dip(40);
//动画执行的时间
private long TRANSLATION_TIME = 350;
//是否停止动画
private boolean mIsStopAnimator = false;
public LoadView(Context context) {
this(context, null);
}
public LoadView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public LoadView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
//添加三个view,但是要圆形
mLeftView = getCircleView(context);
//设置小球颜色
mLeftView.exchangeColor(Color.BLUE);
mMiddleView = getCircleView(context);
mMiddleView.exchangeColor(Color.RED);
mRightView = getCircleView(context);
mRightView.exchangeColor(Color.GREEN);
//将小球添加到布局中
addView(mLeftView);
addView(mRightView);
addView(mMiddleView);
post(new Runnable() {
@Override
public void run() {
//布局实例化好之后再去开启动画
expendAnimation();
}
});
}
/**
* 展开动画
*/
private void expendAnimation() {
if (mIsStopAnimator) {
return;
}
//左边跑
ObjectAnimator leftTranslation = ObjectAnimator.ofFloat(mLeftView, "translationX", 0, -MTRANSLATION_DISTANCE);
//往右边跑
ObjectAnimator rightTranslation = ObjectAnimator.ofFloat(mRightView, "translationX", 0, MTRANSLATION_DISTANCE);
//实例化动画集合
AnimatorSet set = new AnimatorSet();
set.setDuration(TRANSLATION_TIME);
//弹性效果 插值器
set.setInterpolator(new DecelerateInterpolator());
//动画一起执行
set.playTogether(leftTranslation, rightTranslation);
//监听动画执行
set.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
//往里面跑
innerAnimation();
}
});
set.start();
}
/**
* 往里面跑动画
*/
private void innerAnimation() {
if (mIsStopAnimator) {
return;
}
//左边跑
ObjectAnimator leftTranslation = ObjectAnimator.ofFloat(mLeftView, "translationX", -MTRANSLATION_DISTANCE, 0);
//往右边跑
ObjectAnimator rightTranslation = ObjectAnimator.ofFloat(mRightView, "translationX", MTRANSLATION_DISTANCE, 0);
AnimatorSet set = new AnimatorSet();
set.setDuration(TRANSLATION_TIME);
//弹性效果 插值器
set.setInterpolator(new AccelerateInterpolator());
//动画一起执行
set.playTogether(leftTranslation, rightTranslation);
//监听动画执行
set.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
//往外面跑
//切换颜色 切换颜色的顺序 左边的给中间,中间的给右边,右边的给左边
int leftColor = mLeftView.getColor();
int rightColor = mRightView.getColor();
int middleColor = mMiddleView.getColor();
//改变颜色
mRightView.exchangeColor(middleColor);
mLeftView.exchangeColor(rightColor);
mMiddleView.exchangeColor(leftColor);
expendAnimation();
}
});
set.start();
}
/**
* 实例化三个小圆
*
* @param context
* @return
*/
public CircleView getCircleView(Context context) {
CircleView circleView = new CircleView(context);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(dip(12), dip(12));
//设置居中
params.addRule(RelativeLayout.CENTER_IN_PARENT);
circleView.setLayoutParams(params);
return circleView;
}
private int dip(int dip) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dip, getResources().getDisplayMetrics());
}
@Override
public void setVisibility(int visibility) {
super.setVisibility(View.INVISIBLE);//不要再去摆放和计算,少走一些系统的源码
//清除掉动画
mLeftView.clearAnimation();
mRightView.clearAnimation();
//把LoadingView从父布局移除
ViewGroup parent = (ViewGroup) getParent();
if (parent != null) {
parent.removeView(this);//从父布局移除
//移除自己里面的所有View
removeAllViews();
}
mIsStopAnimator = true;
}
}
上面就是第二步和第三步的具体实现逻辑,这样子效果就实现了。
源码地址: