實現效果:
實現思路:
1.首先繪製小圓的位置:
每個小圓的間隔爲:2 * Math.PI / CIRCLE_COUNT
2.通過控制第一個小圓的角度變化,控制小圓的旋轉。
通過控制大圓半徑,實現小圓的聚合
3.水波紋實現:繪製一個空心圓,通過不斷改變空心圓的半徑和畫筆寬度。
代碼實現:
package com.test.paintdemo;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Shader;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.LinearInterpolator;
/**
* Created by ygdx_lk on 17/6/26.
*/
public class RingStartLoading extends View {
private final Paint mPaint;
private final LinearGradient linearGradient;
private int width, height;//控件寬,高
private double diagonal;//對角線長度
private final int CIRCLE_COUNT = 6;
private final int RADIUS = 100;//大圓半徑
private float radius = RADIUS;//大圓半徑
private final int RADIUS_SMALL = 20;//小圓半徑
private final int[] COLORS = {Color.RED, Color.BLUE, Color.GREEN, Color.YELLOW};
private float startAngle = 0;//起始角度
private static final String TAG = "RingStartLoading";
private boolean waterRippleStart;
public RingStartLoading(Context context) {
super(context);
mPaint = new Paint();
mPaint.setAntiAlias(true);
linearGradient = new LinearGradient(0, 0, 200, 200, COLORS, null, Shader.TileMode.MIRROR);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//畫布平移到屏幕中心點
canvas.translate(width / 2, height / 2);
mPaint.reset();
mPaint.setAntiAlias(true);
if(waterRippleStart){
//繪製水波紋效果
drawWaterRipple(canvas);
}
if(radius <= RADIUS) {
//繪製圓
drawCircles(canvas);
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
startAnim();
break;
}
return super.onTouchEvent(event);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
width = w;
height = h;
//計算屏幕對角線長度
diagonal = Math.ceil(Math.sqrt(w * w + h * h));
}
//繪製水波紋
private void drawWaterRipple(Canvas canvas) {
//繪製背景
mPaint.setStrokeWidth(1);
mPaint.setShader(linearGradient);
canvas.drawRect(-width/2, -height/2, width/2, height/2, mPaint);
mPaint.setShader(null);
//得到畫筆的寬度
float strokeWidth = (float) (diagonal / 2 - radius);
mPaint.setStrokeWidth(strokeWidth);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(Color.WHITE);
//畫圓的半徑 = radius + 畫筆寬度/2
float waterRippleRadius = radius + strokeWidth / 2;
canvas.drawCircle(0, 0, waterRippleRadius, mPaint);
}
//繪製CIRCLE_COUNT個圓
private void drawCircles(Canvas canvas) {
//計算相鄰圓的角度
double angle = 2 * Math.PI / CIRCLE_COUNT;
mPaint.setStrokeWidth(1);
mPaint.setStyle(Paint.Style.FILL);
//繪製圓
for (int i = 0; i < CIRCLE_COUNT; i++) {
float x = (float) (radius * Math.cos(startAngle + angle * i));//計算圓心x座標
float y = (float) (radius * Math.sin(startAngle + angle * i));//計算圓心y座標
mPaint.setColor(COLORS[i % COLORS.length]);
canvas.drawCircle(x, y, RADIUS_SMALL, mPaint);
}
}
//啓動動畫
private void startAnim(){
ValueAnimator valueAnimator = ValueAnimator.ofFloat(0f, (float)(Math.PI * 2));
valueAnimator.setDuration(2000);
valueAnimator.setInterpolator(new LinearInterpolator());
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
startAngle = (float) animation.getAnimatedValue();
postInvalidate();
}
});
final ValueAnimator radiusAnimator = ValueAnimator.ofFloat(RADIUS, 0);
radiusAnimator.setDuration(2000);
radiusAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
radius = (float) animation.getAnimatedValue();
postInvalidate();
}
});
ValueAnimator waterRippleAnimator = ValueAnimator.ofFloat(0, (float)diagonal / 2);
waterRippleAnimator.setDuration(4000);
waterRippleAnimator.setInterpolator(new LinearInterpolator());
waterRippleAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
waterRippleStart = true;
radius = (float) animation.getAnimatedValue();
postInvalidate();
}
});
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.playSequentially(valueAnimator, radiusAnimator, waterRippleAnimator);
animatorSet.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
super.onAnimationStart(animation);
radius = RADIUS;
waterRippleStart = false;
}
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
animation.start();
}
});
animatorSet.start();
}
}