实现效果:
实现思路:
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();
}
}