package com.gospelware.liquidbutton;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.View;
import com.gospelware.liquidbutton.controller.BaseController;
import com.gospelware.liquidbutton.controller.PourFinishController;
import com.gospelware.liquidbutton.controller.PourStartController;
import com.gospelware.liquidbutton.controller.TickController;
import com.gospelware.liquidbutton.controller.WaveController;
import java.util.ArrayList;
import java.util.List;
/**
* Created by ricogao on 12/05/2016.
*/
public class LiquidButton extends View {
private PourFinishListener listener;
private boolean isFillAfter;
private boolean isAutoPlay;
private boolean drawFillAfterFlag;
private Animator startAnim, waveAnim, finishAnim;
private BaseController startController;
private WaveController waveController;
private List<BaseController> finishControllers;
public LiquidButton(Context context) {
this(context, null);
}
public LiquidButton(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public LiquidButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
/**
* Basic Animations to build the LiquidButton
*/
private void init() {
startController = new PourStartController();
startController.setCheckView(this);
waveController = new WaveController();
waveController.setCheckView(this);
PourFinishController finishController = new PourFinishController();
finishController.setCheckView(this);
TickController tickController = new TickController();
tickController.setCheckView(this);
List<BaseController> finishControllers = new ArrayList<>();
finishControllers.add(finishController);
finishControllers.add(tickController);
this.finishControllers = finishControllers;
}
public void setFillAfter(boolean fillAfter) {
this.isFillAfter = fillAfter;
}
public boolean isFillAfter() {
return isFillAfter;
}
private void onFillAfter(Canvas canvas) {
//draw the last frame of the last controller
BaseController controller = finishControllers.get(finishControllers.size() - 1);
if (!controller.isRunning()) {
controller.draw(canvas);
}
}
public boolean isAutoPlay() {
return isAutoPlay;
}
public void setAutoPlay(boolean autoPlay) {
isAutoPlay = autoPlay;
}
public interface PourFinishListener {
void onPourFinish();
void onProgressUpdate(float progress);
}
private void onFinishPour() {
if (listener != null) {
listener.onPourFinish();
}
}
public void setPourFinishListener(PourFinishListener listener) {
this.listener = listener;
if (waveController != null) {
waveController.setPourFinishListener(listener);
}
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
int width = getWidth();
int height = getHeight();
startController.getMeasure(width, height);
waveController.getMeasure(width, height);
for (BaseController controller : finishControllers) {
controller.getMeasure(width, height);
}
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
BaseController controller = getRunningController();
if (controller != null) {
controller.draw(canvas);
}
//if the fill after flag is on, draw the lastFrame
if (drawFillAfterFlag) {
onFillAfter(canvas);
}
}
private BaseController getRunningController() {
if (startController.isRunning()) {
return startController;
} else if (waveController.isRunning()) {
return waveController;
} else {
for (BaseController controller : finishControllers) {
if (controller.isRunning()) {
return controller;
}
}
}
return null;
}
private Animator buildStartAnimator() {
Animator animator = startController.getAnimator();
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
startWaveAnimator();
if (isAutoPlay()) {
LiquidButton.this.changeProgress(1f);
}
}
});
return animator;
}
private Animator buildFinishAnimator() {
AnimatorSet animatorSet = new AnimatorSet();
List<Animator> animators = new ArrayList<>();
for (BaseController controller : finishControllers) {
animators.add(controller.getAnimator());
}
animatorSet.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
onPourEnd();
onFinishPour();
LiquidButton.this.setClickable(true);
}
});
animatorSet.playSequentially(animators);
return animatorSet;
}
private void startWaveAnimator() {
if (waveAnim == null) {
waveAnim = waveController.getAnimator();
}
waveAnim.start();
}
public void startPour() {
if(startAnim==null) {
startAnim = buildStartAnimator();
}
//clear the fillAfterFlag
if (drawFillAfterFlag) {
drawFillAfterFlag = false;
}
startAnim.start();
this.setClickable(false);
}
public void finishPour() {
if (waveController.getLiquidProgress() >= 1f) {
if (finishAnim == null) {
finishAnim = buildFinishAnimator();
}
finishAnim.start();
} else {
changeProgress(1f);
}
}
private void onPourEnd() {
//turn the fillAfter flag ON if it's been set
drawFillAfterFlag = isFillAfter();
if (drawFillAfterFlag) {
postInvalidate();
}
}
/**
* This method only works when the given progress is larger than current progress
* When progress is 1, it automatically starts the finish animation.
*
* @param progress
*/
public void changeProgress(float progress) {
if (waveController.isRunning()) {
waveController.changeProgress(progress);
}
}
}