package com.marshalchen.common.uimodule.materialanimatedswitch.painter; import android.animation.Animator; import android.animation.ValueAnimator; import android.content.Context; import android.graphics.Bitmap; import com.marshalchen.common.uimodule.materialanimatedswitch.MaterialAnimatedSwitchState; import com.marshalchen.common.uimodule.materialanimatedswitch.observer.BallFinishObservable; import com.marshalchen.ultimateandroiduilollipop.R; import java.util.Observable; import java.util.Observer; /** * @author Adrián García Lomas */ public class IconReleasePainter extends IconPainter { private ValueAnimator enterXAnimator; private ValueAnimator enterYAnimator; private ValueAnimator exitXAnimator; private ValueAnimator exitYAnimator; private ValueAnimator exitAlphaAnimator; private int enterYAnimationStart; private int exitYAnimatorFinish; private int exitXAnimationStart; private BallFinishObservable ballFinishObservable; private MaterialAnimatedSwitchState actualState; private int iconMargin; private int middle; private boolean alphaEnterTrigger = false; public IconReleasePainter(Context context, Bitmap bitmap, BallFinishObservable ballFinishObservable, int margin) { super(context, bitmap, margin); initValueAnimator(); this.ballFinishObservable = ballFinishObservable; initObserver(); } @Override protected void initBitmap() { super.initBitmap(); } private void initValueAnimator() { int movementAnimationDuration = context.getResources().getInteger(R.integer.mas_animation_duration); int alphaAnimationDuration = context.getResources().getInteger(R.integer.mas_alpha_animation_duration); int curveCompensation = context.getResources().getInteger(R.integer.mas_animation_curvature_compensation); enterXAnimator = ValueAnimator.ofInt(0, width); enterXAnimator.setDuration(movementAnimationDuration); enterXAnimator.addUpdateListener(new EnterXAnimationListener()); exitXAnimator = ValueAnimator.ofInt(); exitXAnimator.setDuration(movementAnimationDuration); exitXAnimator.addUpdateListener(new EnterXAnimationListener()); enterYAnimator = ValueAnimator.ofInt(width, 0); enterYAnimator.setDuration(movementAnimationDuration - curveCompensation); enterYAnimator.addUpdateListener(new EnterYAnimationListener()); exitYAnimator = ValueAnimator.ofInt(); exitYAnimator.setDuration(movementAnimationDuration); exitYAnimator.addUpdateListener(new EnterYAnimationListener()); exitAlphaAnimator = ValueAnimator.ofInt(0, 255); exitAlphaAnimator.setDuration(alphaAnimationDuration); exitAlphaAnimator.addUpdateListener(new AlphaAnimatorUpdateListener()); exitAlphaAnimator.addListener(new AlphaAnimatorStateListener()); } @Override public void setColor(int color) { //Empty } @Override public int getColor() { return 0; } @Override public void setState(MaterialAnimatedSwitchState state) { this.actualState = state; switch (state) { case INIT: isVisible = true; break; case PRESS: exitYAnimator.start(); exitXAnimator.reverse(); exitAlphaAnimator.reverse(); break; case RELEASE: isVisible = true; enterXAnimator.reverse(); enterYAnimator.start(); break; } } private void initObserver() { ballFinishObservable.addObserver(new BallFinishListener()); } private class BallFinishListener implements Observer { @Override public void update(Observable observable, Object data) { BallFinishObservable.BallState ballState = ((BallFinishObservable) observable).getState(); switch (ballState) { case PRESS: isVisible = false; break; } } } @Override public void onSizeChanged(int height, int width) { super.onSizeChanged(height, width); initValues(); initAnimationsValues(); iconYPosition = middle - (iconMargin); iconXPosition = margin - iconMargin; enterXAnimator.setIntValues(0, width); enterYAnimator.setIntValues(enterYAnimationStart, middle); exitYAnimator.setIntValues(middle, exitYAnimatorFinish); exitXAnimator.setIntValues(exitXAnimationStart, 0); } private void initValues() { iconMargin = imageWidth / 2; middle = height / 2; } private void initAnimationsValues() { exitXAnimationStart = (int) context.getResources().getDimension(R.dimen.mas_exitXAnimationStart); exitYAnimatorFinish = (int) context.getResources().getDimension(R.dimen.mas_exitYAnimatorFinish); enterYAnimationStart = (int) context.getResources().getDimension(R.dimen.mas_enterYAnimationStart); } /** * Update the icon position in the x axis */ private class EnterXAnimationListener implements ValueAnimator.AnimatorUpdateListener { @Override public void onAnimationUpdate(ValueAnimator animation) { iconXPosition = ((int) animation.getAnimatedValue()) - iconMargin + margin; } } /** * Move the icon in the y axis and perform a trigger */ private class EnterYAnimationListener implements ValueAnimator.AnimatorUpdateListener { @Override public void onAnimationUpdate(ValueAnimator animation) { iconYPosition = ((int) animation.getAnimatedValue() - iconMargin); if (animation.getCurrentPlayTime() > animation.getDuration() / 2 && !alphaEnterTrigger && actualState.equals(MaterialAnimatedSwitchState.RELEASE)) { exitAlphaAnimator.start(); alphaEnterTrigger = true; } } } /** * Update the alpha */ private class AlphaAnimatorUpdateListener implements ValueAnimator.AnimatorUpdateListener { @Override public void onAnimationUpdate(ValueAnimator animation) { paint.setAlpha((Integer) animation.getAnimatedValue()); } } /** * Set alpha trigger to false on animation end */ private class AlphaAnimatorStateListener implements ValueAnimator.AnimatorListener { @Override public void onAnimationStart(Animator animation) { //Empty } @Override public void onAnimationEnd(Animator animation) { alphaEnterTrigger = false; } @Override public void onAnimationCancel(Animator animation) { //Empty } @Override public void onAnimationRepeat(Animator animation) { //Empty } } }