package com.marshalchen.common.uimodule.googleprogressbar;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.view.animation.Interpolator;
import android.view.animation.LinearInterpolator;
import com.marshalchen.ultimateandroiduilollipop.R;
/**
* Nexus One rotation cross animation progress.
*
* @author Oleksandr Melnykov
*/
public class NexusRotationCrossDrawable extends Drawable implements Drawable.Callback {
private static final int ANIMATION_DURATION = 150;
private static final int ANIMATION_START_DELAY = 300;
private static final Interpolator LINEAR_INTERPOLATOR = new LinearInterpolator();
private int mCenter;
private Point[] mArrowPoints;
private Path mPath;
private Paint mPaint1;
private Paint mPaint2;
private Paint mPaint3;
private Paint mPaint4;
private int mRotationAngle;
public NexusRotationCrossDrawable(int[] colors) {
mArrowPoints = new Point[5];
mPath = new Path();
mPaint1 = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint1.setColor(colors[0]);
mPaint2 = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint2.setColor(colors[1]);
mPaint3 = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint3.setColor(colors[2]);
mPaint4 = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint4.setColor(colors[3]);
initObjectAnimator();
}
private void initObjectAnimator() {
final ObjectAnimator objectAnimator = ObjectAnimator.ofInt(this, "rotationAngle", 0, 180);
objectAnimator.setInterpolator(LINEAR_INTERPOLATOR);
objectAnimator.setDuration(ANIMATION_DURATION);
objectAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
if (mRotationAngle == 180) {
objectAnimator.setIntValues(180, 360);
objectAnimator.setStartDelay(ANIMATION_START_DELAY * 2);
} else {
objectAnimator.setIntValues(0, 180);
objectAnimator.setStartDelay(ANIMATION_START_DELAY);
mRotationAngle = 0;
}
objectAnimator.start();
}
});
objectAnimator.start();
}
@Override
public void draw(Canvas canvas) {
drawArrows(canvas);
}
private void drawArrows(Canvas canvas) {
canvas.rotate(mRotationAngle, mCenter, mCenter);
mPath.reset();
mPath.moveTo(mArrowPoints[0].x, mArrowPoints[0].y);
for (int i = 1; i < mArrowPoints.length; i++) {
mPath.lineTo(mArrowPoints[i].x, mArrowPoints[i].y);
}
mPath.lineTo(mArrowPoints[0].x, mArrowPoints[0].y);
canvas.save();
canvas.drawPath(mPath, mPaint1);
canvas.restore();
canvas.save();
canvas.rotate(90, mCenter, mCenter);
canvas.drawPath(mPath, mPaint2);
canvas.restore();
canvas.save();
canvas.rotate(180, mCenter, mCenter);
canvas.drawPath(mPath, mPaint3);
canvas.restore();
canvas.save();
canvas.rotate(270, mCenter, mCenter);
canvas.drawPath(mPath, mPaint4);
canvas.restore();
}
@Override
public void invalidateDrawable(Drawable who) {
final Callback callback = getCallback();
if (callback != null) {
callback.invalidateDrawable(this);
}
}
@Override
public void scheduleDrawable(Drawable who, Runnable what, long when) {
final Callback callback = getCallback();
if (callback != null) {
callback.scheduleDrawable(this, what, when);
}
}
@Override
public void unscheduleDrawable(Drawable who, Runnable what) {
final Callback callback = getCallback();
if (callback != null) {
callback.unscheduleDrawable(this, what);
}
}
@Override
public void setAlpha(int alpha) {
mPaint1.setAlpha(alpha);
mPaint2.setAlpha(alpha);
mPaint3.setAlpha(alpha);
mPaint4.setAlpha(alpha);
}
@Override
public void setColorFilter(ColorFilter cf) {
mPaint1.setColorFilter(cf);
mPaint2.setColorFilter(cf);
mPaint3.setColorFilter(cf);
mPaint4.setColorFilter(cf);
}
@Override
protected void onBoundsChange(Rect bounds) {
super.onBoundsChange(bounds);
measureDrawable(bounds);
}
private void measureDrawable(Rect bounds) {
mCenter = bounds.centerX();
int arrowMargin = bounds.width() / 50;
int arrowWidth = bounds.width() / 15;
int padding = mCenter - (int) (mCenter / Math.sqrt(2));
mArrowPoints[0] = new Point(mCenter - arrowMargin, mCenter - arrowMargin);
mArrowPoints[1] = new Point(mArrowPoints[0].x, mArrowPoints[0].y - arrowWidth);
mArrowPoints[2] = new Point(padding + arrowWidth, padding);
mArrowPoints[3] = new Point(padding, padding + arrowWidth);
mArrowPoints[4] = new Point(mArrowPoints[0].x - arrowWidth, mArrowPoints[0].y);
}
@Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
void setRotationAngle(int angle) {
mRotationAngle = angle;
}
int getRotationAngle() {
return mRotationAngle;
}
public static class Builder {
private int[] mColors;
public Builder(Context context) {
initDefaults(context);
}
private void initDefaults(Context context) {
mColors = context.getResources().getIntArray(R.array.google_colors);
}
public Builder colors(int[] colors) {
if (colors == null || colors.length != 4) {
throw new IllegalArgumentException("Your color array must contains 4 values");
}
mColors = colors;
return this;
}
public Drawable build() {
return new NexusRotationCrossDrawable(mColors);
}
}
}