package com.androidexperiments.landmarker.widget;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.content.Context;
import android.util.AttributeSet;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.animation.AnticipateInterpolator;
import android.view.animation.OvershootInterpolator;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.google.creativelabs.androidexperiments.typecompass.R;
import com.androidexperiments.landmarker.util.SimpleAnimationListener;
import butterknife.ButterKnife;
import butterknife.InjectView;
import butterknife.OnClick;
import de.greenrobot.event.EventBus;
/**
* Figure 8 animation
*/
public class SwingPhoneView extends RelativeLayout
{
private static final String TAG = SwingPhoneView.class.getSimpleName();
@InjectView(R.id.swipe_phone_figure_8) ImageView mFigure8View;
@InjectView(R.id.swipe_phone_image) ImageView mPhoneImageView;
@InjectView(R.id.swing_phone_text) TextView mText;
private Animation mScaleIn, mFromBottom, mScaleOut;
public SwingPhoneView(Context context) {
super(context);
}
public SwingPhoneView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SwingPhoneView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
ButterKnife.inject(this,this);
mScaleIn = AnimationUtils.loadAnimation(getContext(), R.anim.scale_in);
mScaleIn.setInterpolator(new OvershootInterpolator(1.2f));
mScaleOut = AnimationUtils.loadAnimation(getContext(), R.anim.scale_out);
mScaleOut.setInterpolator(new AnticipateInterpolator(1.2f));
mFromBottom = AnimationUtils.loadAnimation(getContext(), R.anim.show_from_bottom);
mFromBottom.setStartOffset(250);
}
@OnClick(R.id.swipe_phone_image)
public void onClickPhone() {
startLoop();
}
public void animateIn() {
this.setVisibility(VISIBLE);
mFigure8View.startAnimation(mScaleIn);
mText.startAnimation(mFromBottom);
startLoop();
}
private void startLoop()
{
float pi = (float)Math.PI;
ValueAnimator animator = ValueAnimator.ofFloat(pi / 2, -pi - pi / 2);
animator.setDuration(1750);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
float lastVal = 0.f;
@Override
public void onAnimationUpdate(ValueAnimator animation)
{
double t = Double.parseDouble(animation.getAnimatedValue().toString());
double scale = 2 / (3 - Math.cos(2.*t));
float unscaledX = (float)Math.cos(t);
float x = (float)scale * unscaledX;
float y = (float)scale * (float)Math.sin(2 * t) / 2;
mPhoneImageView.setTranslationX(x * (mFigure8View.getWidth() / 2));
mPhoneImageView.setTranslationY(y * (mFigure8View.getHeight()));
float rotation;
float half = .55f;
// moving right
if(x >= lastVal) {
if(x <= 0.f) {
if(x < -half)
rotation = map(x, -1, -half, -90, 0);
else
rotation = map(x, -half, 0f, 0, 30);
}
else {
if(x > half)
rotation = map(x, half, 1, 0, -90);
else
rotation = map(x, 0, half, 30, 0);
}
}
// moving left
else {
if(x >= 0.f) {
if(x > half)
rotation = map(x, 1, half, -90, -180);
else
rotation = map(x, half, 0, -180, -210);
}
else {
if (x < -half)
rotation = map(x, -1, -half, -90, -180);
else
rotation = map(x, -half, 0, -180, -210);
}
}
mPhoneImageView.setRotation(rotation);
lastVal = x;
}
});
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
animateOut();
}
});
animator.setInterpolator(null);
animator.setRepeatCount(2);//ValueAnimator.INFINITE);
animator.setRepeatMode(ValueAnimator.RESTART);
animator.start();
}
private void animateOut()
{
this.setVisibility(GONE);
this.startAnimation(mScaleOut);
mScaleOut.setAnimationListener(new SimpleAnimationListener() {
@Override
public void onAnimationEnd(Animation animation) {
EventBus.getDefault().post(new OnAnimateOutCompleteEvent());
}
});
}
public final float map(float value, float start1, float stop1, float start2, float stop2) {
return start2 + (stop2 - start2) * ((value - start1) / (stop1 - start1));
}
//event bus
public static class OnAnimateOutCompleteEvent { }
}