package com.marshalchen.common.uimodule.materialanimatedswitch.painter;
import android.animation.Animator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import com.marshalchen.common.uimodule.materialanimatedswitch.observer.BallFinishObservable;
import com.marshalchen.common.uimodule.materialanimatedswitch.observer.BallMoveObservable;
import com.marshalchen.common.uimodule.materialanimatedswitch.MaterialAnimatedSwitchState;
import com.marshalchen.ultimateandroiduilollipop.R;
/**
* @author Adrián García Lomas
*/
public class BallPainter implements SwitchInboxPinnedPainter {
protected Paint paint;
protected Paint toBgPainter;
protected int padding;
protected int height;
protected int width;
protected int radius;
protected int ballPositionX;
protected int ballStartPositionX;
protected int ballMovementRange;
private ValueAnimator moveAnimator;
private ValueAnimator colorAnimator;
private MaterialAnimatedSwitchState actualState;
private BallFinishObservable ballFinishObservable;
private BallMoveObservable ballMoveObservable;
private Context context;
private int middle;
private int bgColor;
private int toBgColor;
public BallPainter(int bgColor, int toBgColor, int padding,
BallFinishObservable ballFinishObservable, BallMoveObservable ballMoveObservable,
Context context) {
this.bgColor = bgColor;
this.toBgColor = toBgColor;
this.padding = padding;
this.ballFinishObservable = ballFinishObservable;
this.ballMoveObservable = ballMoveObservable;
this.context = context;
init();
}
private void init() {
paint = new Paint();
paint.setColor(bgColor);
paint.setStyle(Paint.Style.FILL);
paint.setAntiAlias(true);
toBgPainter = new Paint();
toBgPainter.setColor(toBgColor);
toBgPainter.setStyle(Paint.Style.FILL);
toBgPainter.setAntiAlias(true);
toBgPainter.setAlpha(0);
radius = (int) context.getResources().getDimension(R.dimen.mas_ball_radius);
ballStartPositionX = (int) context.getResources().getDimension(R.dimen.mas_ball_start_position);
ballPositionX = padding;
}
private void initAnimator() {
int from = padding;
int to = width - padding;
ballMovementRange = to - from;
moveAnimator = ValueAnimator.ofInt(from, to);
moveAnimator.addUpdateListener(new BallAnimatorListener());
moveAnimator.addListener(new BallAnimatorFinishListener());
}
private void initColorAnimator() {
colorAnimator = ValueAnimator.ofInt(0, 255);
colorAnimator.setDuration(ballMovementRange);
colorAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override public void onAnimationUpdate(ValueAnimator animation) {
toBgPainter.setAlpha((Integer) animation.getAnimatedValue());
}
});
}
@Override public void draw(Canvas canvas) {
canvas.drawCircle(ballPositionX, middle, radius, paint);
canvas.drawCircle(ballPositionX, middle, radius, toBgPainter);
}
@Override public void setColor(int color) {
this.bgColor = color;
}
@Override public int getColor() {
return bgColor;
}
@Override public void onSizeChanged(int height, int width) {
this.height = height;
this.width = width;
middle = height / 2;
initAnimator();
initColorAnimator();
}
@Override public void setState(MaterialAnimatedSwitchState state) {
switch (state) {
case PRESS:
actualState = MaterialAnimatedSwitchState.PRESS;
moveAnimator.start();
break;
case RELEASE:
actualState = MaterialAnimatedSwitchState.RELEASE;
moveAnimator.reverse();
}
}
private class BallAnimatorFinishListener implements ValueAnimator.AnimatorListener {
@Override public void onAnimationStart(Animator animation) {
ballFinishObservable.setBallState(BallFinishObservable.BallState.MOVE);
}
@Override public void onAnimationEnd(Animator animation) {
if (actualState.equals(MaterialAnimatedSwitchState.PRESS)) {
ballFinishObservable.setBallState(BallFinishObservable.BallState.PRESS);
} else {
ballFinishObservable.setBallState(BallFinishObservable.BallState.RELEASE);
}
}
@Override public void onAnimationCancel(Animator animation) {
//Empty
}
@Override public void onAnimationRepeat(Animator animation) {
//Empty
}
}
private class BallAnimatorListener implements ValueAnimator.AnimatorUpdateListener {
@Override public void onAnimationUpdate(ValueAnimator animation) {
int value = (int) animation.getAnimatedValue();
//Move the ball
ballPositionX = value;
//1- Get pixel of movement from 0 to movementRange
int pixelMove = value - padding;
//Transform the range movement to a 0 - 100 range
int rangeValue = getAnimatedRange(pixelMove);
//Change the color animation to the actual range value (duration is 100)
colorAnimator.setCurrentPlayTime(rangeValue);
//Set ball position to
ballMoveObservable.setBallPosition(ballPositionX);
//Put this value on a observable the listeners know the state of the movement in a range of 0
//to 100
ballMoveObservable.setBallAnimationValue(rangeValue);
}
private int getAnimatedRange(int value) {
return ((value * 100) / ballMovementRange);
}
}
}