Android高级UI之手写粒子扩散效果
先来看效果图(gif图片看起来有卡顿,真机 不会)
image
1.重写onSizeChanged方法得到 屏幕正中心点坐标
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
// 屏幕正中心点坐标
mCenterX = w /2f;
mCenterY = h /2f;
//屏幕对角线
mDiagonalDist = (float) (Math.sqrt((w * w + h * h)) /2f);//勾股定理
}
2.初始化
public SplashView(Context context) {
super(context);
init(context);
}
private void init(Context context) {
mCircleColors = context.getResources().getIntArray(R.array.splash_circle_colors);
//画笔
mPaint.setAntiAlias(true);
mPaintBackground.setAntiAlias(true);
mPaintBackground.setStyle(Paint.Style.STROKE);
mPaintBackground.setColor(mSplashBgColor);
}
3.新建SplashState 侧列模式
private abstract class SplashState {
public abstract void drawState(Canvas canvas);
public void cencel() {
mAnimator.cancel();
}
}
4.旋转动画
private class RotateState extends SplashState {
public RotateState() {
mAnimator = ValueAnimator.ofFloat(0f, (float) (Math.PI * 2));
mAnimator.setInterpolator(new LinearInterpolator());
mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mCurrentRotationAngle = (float) animation.getAnimatedValue();
postInvalidate();
}
});
mAnimator.setDuration(mRotationDuration);
mAnimator.setRepeatCount(ValueAnimator.INFINITE);
mAnimator.start();
}
@Override
public void drawState(Canvas canvas) {
drawBackground(canvas);
//绘制小圆
draCircles(canvas);
}
}
private void drawBackground(Canvas canvas) {
if (mHoleRadius > 0f) {
mPaintBackground.setColor(Color.WHITE);
float strokeWith= mDiagonalDist-mHoleRadius;
mPaintBackground.setStrokeWidth(strokeWith);
float v = mHoleRadius + strokeWith / 2;
canvas.drawCircle(mCenterX, mCenterY, v, mPaintBackground);
} else {
canvas.drawColor(mSplashBgColor);
}
}
private void draCircles(Canvas canvas) {
Log.e("小圆的圆心点",mCenterX+","+mCenterY);
float rotertionAngle = (float) (2 * Math.PI / mCircleColors.length);
for (int i = 0; i < mCircleColors.length; i++) {
/**
* x=r*cos(a)+mCenterX
* y=r*sin(a)+mCenterY
*/
float angle = i * rotertionAngle + mCurrentRotationAngle;
float cx = (float) (mCurrentRotationRadius * Math.cos(angle) + mCenterX);
float cy = (float) (mCurrentRotationRadius * Math.sin(angle) + mCenterY);
mPaint.setColor(mCircleColors[i]);
canvas.drawCircle(cx, cy, mCircleRadius, mPaint);
}
}
4.集合动画
private class MergingState extends SplashState {
public MergingState() {
mAnimator = ValueAnimator.ofFloat(0f, mRotationRadius);
mAnimator.setDuration(mRotationDuration);
mAnimator.setInterpolator(new OvershootInterpolator(10f));
mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
Log.e("animation====", animation.getAnimatedValue() + "");
mCurrentRotationRadius = (float) animation.getAnimatedValue();
invalidate();
}
});
mAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
mState = new ExpandState();
}
});
mAnimator.reverse();
}
@Override
public void drawState(Canvas canvas) {
drawBackground(canvas);
//绘制小圆
draCircles(canvas);
}
}
5.水波纹扩散动画
private class ExpandState extends SplashState {
public ExpandState() {
mAnimator = ValueAnimator.ofFloat(mCircleRadius, mDiagonalDist);
mAnimator.setDuration(mRotationDuration);
mAnimator.setInterpolator(new LinearInterpolator());
mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mHoleRadius = (float) animation.getAnimatedValue();
invalidate();
}
});
mAnimator.start();
}
@Override
public void drawState(Canvas canvas) {
drawBackground(canvas);
}
}