package io.github.mayubao.kuaichuan.ui.view;
import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.LinearInterpolator;
import android.widget.FrameLayout;
import java.util.ArrayList;
import java.util.List;
/**
* Created by mayubao on 2016/11/26.
* Contact me 345269374@qq.com
*/
public class RadarLayout extends FrameLayout {
public static final int INFINITE = 0;
private static final int DEFAULT_COUNT = 4;
private static final int DEFAULT_COLOR = Color.rgb(0, 116, 193);
private static final int DEFAULT_DURATION = 7000;
private static final int DEFAULT_REPEAT = INFINITE;
private static final int DEFAULT_STROKE_WIDTH = 2;
private int mCount;
private int mDuration;
private int mRepeat;
private AnimatorSet mAnimatorSet;
private Paint mPaint;
private int mColor;
private float mRadius;
private float mCenterX;
private float mCenterY;
private int mStrokeWidth;
private boolean mIsStarted;
private boolean mUseRing;
public RadarLayout(Context context) {
super(context);
initGlobalparams();
}
public RadarLayout(Context context, AttributeSet attrs) {
super(context, attrs);
initGlobalparams();
}
public RadarLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initGlobalparams();
}
private void initGlobalparams() {
mColor = DEFAULT_COLOR;
mCount = DEFAULT_COUNT;
mDuration = DEFAULT_DURATION;
mRepeat = DEFAULT_REPEAT;
mUseRing = false;
mStrokeWidth = dip2px(DEFAULT_STROKE_WIDTH);
build();
}
public synchronized void start() {
if (mAnimatorSet == null || mIsStarted) {
return;
}
mAnimatorSet.start();
}
public synchronized void stop() {
if (mAnimatorSet == null || !mIsStarted) {
return;
}
mAnimatorSet.end();
}
public synchronized boolean isStarted() {
return (mAnimatorSet != null && mIsStarted);
}
public int getCount() {
return mCount;
}
public int getDuration() {
return mDuration;
}
public void setCount(int count) {
if (count < 0) {
throw new IllegalArgumentException("Count cannot be negative");
}
if (count != mCount) {
mCount = count;
reset();
invalidate();
}
}
public void setDuration(int millis) {
if (millis < 0) {
throw new IllegalArgumentException("Duration cannot be negative");
}
if (millis != mDuration) {
mDuration = millis;
reset();
invalidate();
}
}
public void setColor(int color) {
if (mColor != color) {
mColor = color;
reset();
invalidate();
}
}
public void setUseRing(boolean useRing) {
if (mUseRing != useRing) {
mUseRing = useRing;
reset();
invalidate();
}
}
@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = getMeasuredWidth() - getPaddingLeft() - getPaddingRight();
int height = getMeasuredHeight() - getPaddingTop() - getPaddingBottom();
// 确定圆的圆点坐标及半径
mCenterX = width * 0.5f;
mCenterY = height * 0.5f;
mRadius = Math.min(width, height) * 0.5f;
}
private void clear() {
stop();
removeAllViews();
}
private void build() {
LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
int repeatCount = (mRepeat == INFINITE) ? ObjectAnimator.INFINITE : mRepeat;
List animators = new ArrayList();
for (int index = 0; index < mCount; index++) {
RadarView radarView = new RadarView(getContext());
radarView.setScaleX(0);
radarView.setScaleY(0);
radarView.setAlpha(1);
addView(radarView, index, params);
// 计算时间间隔
long delay = index * mDuration / mCount;
// 属性动画
animators.add(create(radarView, "scaleX", repeatCount, delay, 0, 1));
animators.add(create(radarView, "scaleY", repeatCount, delay, 0, 1));
animators.add(create(radarView, "alpha", repeatCount, delay, 1, 0));
}
mAnimatorSet = new AnimatorSet();
mAnimatorSet.playTogether(animators);
mAnimatorSet.setInterpolator(new LinearInterpolator());
mAnimatorSet.setDuration(mDuration);
mAnimatorSet.addListener(mAnimatorListener);
}
private ObjectAnimator create(View target, String propertyName, int repeatCount, long delay, float from, float to) {
ObjectAnimator animator = ObjectAnimator.ofFloat(target, propertyName, from, to);
animator.setRepeatCount(repeatCount);
animator.setRepeatMode(ObjectAnimator.RESTART);
animator.setStartDelay(delay);
return animator;
}
private void reset() {
boolean isStarted = isStarted();
clear();
build();
if (isStarted) {
start();
}
}
private class RadarView extends View {
public RadarView(Context context) {
super(context);
}
@Override
protected void onDraw(Canvas canvas) {
if (null == mPaint) {
mPaint = new Paint();
mPaint.setColor(mColor);
mPaint.setAntiAlias(true);
// 注意Style的用法,【STROKE:画环】【FILL:画圆】
mPaint.setStyle(mUseRing ? Paint.Style.STROKE : Paint.Style.FILL);
mPaint.setStrokeWidth(mUseRing ? mStrokeWidth : 0);
}
// 画圆或环
canvas.drawCircle(mCenterX, mCenterY, mUseRing ? mRadius - mStrokeWidth : mRadius, mPaint);
}
}
private int dip2px(float dpValue) {
final float scale = getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
private final Animator.AnimatorListener mAnimatorListener = new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animator) {
mIsStarted = true;
}
@Override
public void onAnimationEnd(Animator animator) {
mIsStarted = false;
}
@Override
public void onAnimationCancel(Animator animator) {
mIsStarted = false;
}
@Override
public void onAnimationRepeat(Animator animator) {
}
};
}