先上效果图
其实上边效果分为几个部分,一个部分是多个小星星四处扩散,第二个部分是一个小星星从小变大,还有一个是实心圆的动画。
代码如下
第一:所有的小星星动画
public class StarView extends View {
private Paint mPaint;
private Bitmap mStar; // 星星图片
private ArrayList<StarModel> mStarModelList = null;
private float mCurrentProgress; // 当前进度
private int mCenterX, mCenterY; // 中心点
private ValueAnimator mValueAnimator;
public StarView(Context context) {
this(context, null);
}
public StarView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public StarView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mStar = BitmapFactory.decodeResource(getResources(), R.mipmap.stars1);
}
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
mCenterX = getMeasuredWidth() / 2 - mStar.getWidth() / 2; // 90
mCenterY = getMeasuredHeight() / 2 - mStar.getHeight() / 2; // 90
}
@Override protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mStarModelList == null) {
return;
}
for (StarModel starModel : mStarModelList) {
starModel.draw(canvas, mPaint, mCurrentProgress, mCenterX, mCenterY);
}
}
public ValueAnimator startAnimation(int length, int duration, int delay) {
if (mStarModelList != null) {
mStarModelList.clear();
mValueAnimator = null;
}
initStarModel(length);
mValueAnimator = ValueAnimator.ofFloat(0f, 1f);
mValueAnimator.setInterpolator(new DecelerateInterpolator());
mValueAnimator.setDuration(duration);
mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override public void onAnimationUpdate(ValueAnimator animation) {
mCurrentProgress = (float) animation.getAnimatedValue();
invalidate();
}
});
mValueAnimator.setStartDelay(delay);
mValueAnimator.start();
return mValueAnimator;
}
private void initStarModel(int length) {
mStarModelList = new ArrayList<>(10);
Random random = new Random();
for (int i = 0; i < length; i++) {
float angle = 0f;
float startX = 0f;
float startY = 0f;
float speed = 1 + random.nextInt(5); // 总共是19
float scale = 1f; // 开始大小
if (i == 0) {
angle = (float) ((10 + 270) * Math.PI / 180);
startX = (float) Math.cos(angle) * mCenterX * 0.05f;
startY = (float) Math.sin(angle) * mCenterY * 0.5f;
// speed = 0.5789f;
} else if (i == 1) {
angle = (float) ((30 + 270) * Math.PI / 180);
startX = (float) Math.cos(angle) * mCenterX * 0.1f;
startY = (float) Math.sin(angle) * mCenterY * 0.2f;
// speed = 0.7368f;
} else if (i == 2) {
angle = (float) ((40 + 270) * Math.PI / 180);
startX = (float) Math.cos(angle) * mCenterX * 0.25f;
startY = (float) Math.sin(angle) * mCenterY * 0.4f;
// speed = 0.5789f;
} else if (i == 3) {
angle = (float) ((60 + 270) * Math.PI / 180);
startX = (float) Math.cos(angle) * mCenterX * 0.3f;
startY = (float) Math.sin(angle) * mCenterY * 0.33f;
// speed = 0.5263f;
} else if (i == 4) { // 星星变小
angle = (float) ((50) * Math.PI / 180);
startX = (float) Math.cos(angle) * mCenterX * 0.6f;
startY = (float) Math.sin(angle) * mCenterY * 0.7f;
scale = 0.8f;
// speed = 0.3157f; // 8
} else if (i == 5) { // 星星变更小
angle = (float) ((80) * Math.PI / 180);
startX = (float) Math.cos(angle) * mCenterX * 0.05f;
startY = (float) Math.sin(angle) * mCenterY * 0.3f;
scale = 0.6f;
// speed = 0.4210f;
} else if (i == 6) {
angle = (float) ((145) * Math.PI / 180);
startX = (float) Math.cos(angle) * mCenterX * 0.5f;
startY = (float) Math.sin(angle) * mCenterY * 0.28f;
// speed = 0.5263f;
} else if (i == 7) {
angle = (float) ((205) * Math.PI / 180);
startX = (float) Math.cos(angle) * mCenterX * 0.5f;
startY = (float) Math.sin(angle) * mCenterY * 0.15f;
scale = 0.8f;
// speed = 0.4210f;
} else if (i == 8) {
angle = (float) ((215) * Math.PI / 180);
startX = (float) Math.cos(angle) * mCenterX * 0.8f;
startY = (float) Math.sin(angle) * mCenterY * 0.35f;
// speed = 0.5789f;
} else if (i == 9) {
angle = (float) ((225) * Math.PI / 180);
startX = (float) Math.cos(angle) * mCenterX * 0.4f;
startY = (float) Math.sin(angle) * mCenterY * 0.5f;
// speed = 0.5789f;
}
Matrix matrix = new Matrix();
StarModel model = new StarModel(mStar, angle, startX, startY, matrix, scale, speed);
mStarModelList.add(model);
}
}
}
第二:圆环动画
public class RingView extends View {
private final static String TAG = "RingView";
private int mDuration = 5000;
private float mCx;
private float mCy;
private float mMaxRadius; // 最大半径
private float mOuterCurrentProgress;
private float mInnerCurrentProgress;
private int[] mColors;
private PorterDuffXfermode mXfermode = new PorterDuffXfermode(PorterDuff.Mode.SRC_IN);
private Paint mPaint; // 绘制外圆
private Paint mInnerPaint;
public RingView(Context context) {
this(context, null);
}
public RingView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public RingView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mColors = getContext().getResources().getIntArray(R.array.clor_ring);
mPaint = new Paint();
mPaint.setColor(mColors[0]);
mInnerPaint = new Paint();
mInnerPaint.setColor(Color.TRANSPARENT);
mInnerPaint.setAlpha(0);
mInnerPaint.setXfermode(mXfermode);
}
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
mCx = getMeasuredWidth() / 2;
mCy = getMeasuredHeight() / 2;
mMaxRadius = mCx;
}
@Override protected void onDraw(Canvas canvas) {
int saveLayer = canvas.saveLayer(0, 0, mCx * 2, mCy * 2, mPaint, Canvas.ALL_SAVE_FLAG);
canvas.drawCircle(mCx, mCx, mOuterCurrentProgress * mMaxRadius, mPaint);
canvas.drawCircle(mCx, mCy, mInnerCurrentProgress * mMaxRadius, mInnerPaint);
canvas.restoreToCount(saveLayer);
}
public void startAnim(int duration) {
ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1f);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override public void onAnimationUpdate(ValueAnimator animation) {
mOuterCurrentProgress = (float) animation.getAnimatedValue();
mPaint.setARGB(255, 255, (int) (229 - mOuterCurrentProgress * 68), 0);
invalidate();
}
});
valueAnimator.setInterpolator(new DecelerateInterpolator()); // 先变快,然后减速
ValueAnimator innerAnimator = ValueAnimator.ofFloat(0.01f, 1f);
innerAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override public void onAnimationUpdate(ValueAnimator animation) {
mInnerCurrentProgress = (float) animation.getAnimatedValue();
invalidate();
}
});
innerAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.setDuration(duration);
animatorSet.playTogether(valueAnimator, innerAnimator);
animatorSet.start();
}
private OnWillEndAnimatorListener onWillEndAnimatorListener;
public void setOnWillEndAnimatorListener(OnWillEndAnimatorListener onWillEndAnimatorListener) {
this.onWillEndAnimatorListener = onWillEndAnimatorListener;
}
public interface OnWillEndAnimatorListener {
void onWillEndAnimatorListener(float value);
}
}
第三结合小星星和圆环
public class StarLayout extends FrameLayout {
private ImageView idIvBigStar; // 大星星
private RingView idRingView; // 圆环
private StarView idSmallStarListView; // 所有的小星星
public StarLayout(@NonNull Context context) {
this(context, null);
}
public StarLayout(@NonNull Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public StarLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
inflate(context, R.layout.layout_star, this);
idIvBigStar = findViewById(R.id.id_iv_big_star);
idRingView = findViewById(R.id.id_ringview);
idSmallStarListView = findViewById(R.id.id_starview);
}
public void startRingAnim(final int[] originLocation) {
final int[] location = new int[2];
idIvBigStar.post(new Runnable() {
@Override public void run() {
idIvBigStar.getLocationInWindow(location);
final int disX = originLocation[0] - location[0];
final int disY = originLocation[1] - location[1];
idIvBigStar.setAlpha(0f);
idRingView.startAnim(400);
startBigStarScaleAnim(1200, 0).start();
idSmallStarListView.startAnimation(10, 1600, 300);
startBitStarTransAndScaleAnim(disX, disY, 1000, 1100);
}
});
}
private Animator startBigStarScaleAnim(int duration, int startDelay) {
ValueAnimator valueAnimator = ValueAnimator.ofFloat(1f, 5f, 8f);
valueAnimator.setInterpolator(new BounceInterpolator());
valueAnimator.addListener(new AnimatorListenerAdapter() {
@Override public void onAnimationStart(Animator animation) {
idIvBigStar.setAlpha(1f);
}
});
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override public void onAnimationUpdate(ValueAnimator animation) {
float value = (float) animation.getAnimatedValue();
idIvBigStar.setScaleX(value);
idIvBigStar.setScaleY(value);
}
});
valueAnimator.setDuration(duration);
valueAnimator.setStartDelay(startDelay);
return valueAnimator;
}
/***
* 平移并且缩放动画
*/
private void startBitStarTransAndScaleAnim(final int disX, final int disY, int duration, int delay) {
ValueAnimator scaleAnim = ValueAnimator.ofFloat(8f, 1f);
scaleAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override public void onAnimationUpdate(ValueAnimator animation) {
float value = (float) animation.getAnimatedValue();
idIvBigStar.setScaleX(value);
idIvBigStar.setScaleY(value);
}
});
ValueAnimator transAnim = ValueAnimator.ofFloat(0, 1f);
transAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override public void onAnimationUpdate(ValueAnimator animation) {
float value = (float) animation.getAnimatedValue();
idIvBigStar.setTranslationX(value * disX);
idIvBigStar.setTranslationY(value * disY);
}
});
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.play(scaleAnim).with(transAnim);
animatorSet.setDuration(duration);
animatorSet.setStartDelay(delay);
animatorSet.addListener(new AnimatorListenerAdapter() {
@Override public void onAnimationEnd(Animator animation) { // 动画执行完毕
if (onAnimationEnd != null) {
onAnimationEnd.onAnimationEnd();
}
}
});
animatorSet.start();
}
private OnAnimationEnd onAnimationEnd;
public void setOnAnimationEnd(OnAnimationEnd onAnimationEnd) {
this.onAnimationEnd = onAnimationEnd;
}
public interface OnAnimationEnd {
void onAnimationEnd();
}
}