package com.fastaccess.helper;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.app.Dialog;
import android.graphics.Rect;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.UiThread;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.app.DialogFragment;
import android.support.v4.view.ViewCompat;
import android.support.v4.view.animation.FastOutLinearInInterpolator;
import android.support.v4.view.animation.LinearOutSlowInInterpolator;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.View;
import android.view.ViewAnimationUtils;
import android.view.ViewPropertyAnimator;
import android.view.ViewTreeObserver;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.Animation;
import android.view.animation.Interpolator;
import android.view.animation.LinearInterpolator;
import android.view.animation.Transformation;
import android.widget.LinearLayout;
import android.widget.PopupWindow;
import java.util.Arrays;
import java.util.List;
/**
* Created by Kosh on 27 May 2016, 9:04 PM
*/
public class AnimHelper {
private static final Interpolator FAST_OUT_LINEAR_IN_INTERPOLATOR = new FastOutLinearInInterpolator();
private static final Interpolator LINEAR_OUT_SLOW_IN_INTERPOLATOR = new LinearOutSlowInInterpolator();
private static final Interpolator interpolator = new LinearInterpolator();
@UiThread private static void animateVisibility(@Nullable final View view, final boolean show, int visibility) {
if (view == null) {
return;
}
if (!ViewCompat.isAttachedToWindow(view)) {
view.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override public boolean onPreDraw() {
view.getViewTreeObserver().removeOnPreDrawListener(this);
animateSafeVisibility(show, view, visibility);
return true;
}
});
} else {
animateSafeVisibility(show, view, visibility);
}
}
@UiThread public static void animateVisibility(@Nullable final View view, final boolean show) {
animateVisibility(view, show, View.GONE);
}
@UiThread private static void animateSafeVisibility(final boolean show, @NonNull final View view, int visibility) {
view.animate().cancel();
ViewPropertyAnimator animator = view.animate().setDuration(200).alpha(show ? 1F : 0F).setInterpolator(new AccelerateInterpolator())
.setListener(new AnimatorListenerAdapter() {
@Override public void onAnimationStart(Animator animation) {
super.onAnimationStart(animation);
if (show) {
view.setScaleX(1);
view.setScaleY(1);
view.setVisibility(View.VISIBLE);
}
}
@Override public void onAnimationEnd(@NonNull Animator animation) {
super.onAnimationEnd(animation);
if (!show) {
view.setVisibility(visibility);
view.setScaleX(0);
view.setScaleY(0);
}
animation.removeListener(this);
view.clearAnimation();
}
});
animator.scaleX(show ? 1 : 0).scaleY(show ? 1 : 0);
}
@UiThread @NonNull private static List<ObjectAnimator> getBeats(@NonNull View view) {
ObjectAnimator[] animator = new ObjectAnimator[]{
ObjectAnimator.ofFloat(view, "scaleY", 1, 1.1f, 1),
ObjectAnimator.ofFloat(view, "scaleX", 1, 1.1f, 1)
};
return Arrays.asList(animator);
}
@UiThread public static void startBeatsAnimation(@NonNull View view) {
view.clearAnimation();
if (view.getAnimation() != null) {
view.getAnimation().cancel();
}
List<ObjectAnimator> animators = getBeats(view);
for (ObjectAnimator anim : animators) {
anim.setDuration(300).start();
anim.setInterpolator(interpolator);
}
}
@UiThread public static void revealPopupWindow(@NonNull PopupWindow popupWindow, @NonNull View from) {
Rect rect = ViewHelper.getLayoutPosition(from);
int x = (int) rect.exactCenterX();
int y = (int) rect.exactCenterY();
if (popupWindow.getContentView() != null) {
View view = popupWindow.getContentView();
if (view != null) {
popupWindow.showAsDropDown(from);
view.post(() -> {
if (ViewCompat.isAttachedToWindow(view)) {
Animator animator = ViewAnimationUtils.createCircularReveal(view, x, y, 0,
(float) Math.hypot(rect.width(), rect.height()));
animator.setDuration(view.getResources().getInteger(android.R.integer.config_shortAnimTime));
animator.start();
}
});
}
}
}
@UiThread public static void revealDialog(@NonNull Dialog dialog, int animDuration) {
if (dialog.getWindow() != null) {
View view = dialog.getWindow().getDecorView();
if (view != null) {
view.post(() -> {
if (ViewCompat.isAttachedToWindow(view)) {
int centerX = view.getWidth() / 2;
int centerY = view.getHeight() / 2;
Animator animator = ViewAnimationUtils.createCircularReveal(view, centerX, centerY, 20, view.getHeight());
animator.setDuration(animDuration);
animator.start();
}
});
}
}
}
@UiThread public static void dismissDialog(@NonNull DialogFragment dialogFragment, int duration, AnimatorListenerAdapter listenerAdapter) {
Dialog dialog = dialogFragment.getDialog();
if (dialog != null) {
if (dialog.getWindow() != null) {
View view = dialog.getWindow().getDecorView();
if (view != null) {
int centerX = view.getWidth() / 2;
int centerY = view.getHeight() / 2;
float radius = (float) Math.sqrt(view.getWidth() * view.getWidth() / 4 + view.getHeight() * view.getHeight() / 4);
view.post(() -> {
if (ViewCompat.isAttachedToWindow(view)) {
Animator animator = ViewAnimationUtils.createCircularReveal(view, centerX, centerY, radius, 0);
animator.setDuration(duration);
animator.addListener(listenerAdapter);
animator.start();
} else {
listenerAdapter.onAnimationEnd(null);
}
});
}
}
} else {
listenerAdapter.onAnimationEnd(null);
}
}
@UiThread public static void mimicFabVisibility(boolean show, @NonNull View view,
@Nullable FloatingActionButton.OnVisibilityChangedListener listener) {
if (show) {
view.animate().cancel();
if (ViewCompat.isLaidOut(view)) {
if (view.getVisibility() != View.VISIBLE) {
view.setAlpha(0f);
view.setScaleY(0f);
view.setScaleX(0f);
}
view.animate()
.scaleX(1f)
.scaleY(1f)
.alpha(1f)
.setDuration(200)
.setInterpolator(LINEAR_OUT_SLOW_IN_INTERPOLATOR)
.withStartAction(() -> {
view.setVisibility(View.VISIBLE);
if (listener != null) listener.onShown(null);
});
} else {
view.setVisibility(View.VISIBLE);
view.setAlpha(1f);
view.setScaleY(1f);
view.setScaleX(1f);
if (listener != null) listener.onShown(null);
}
} else {
view.animate()
.scaleX(0f)
.scaleY(0f)
.alpha(0f)
.setDuration(40)
.setInterpolator(FAST_OUT_LINEAR_IN_INTERPOLATOR);
view.setVisibility(View.GONE);
if (listener != null) listener.onHidden(null);
}
}
public static void expand(final View view) {
view.measure(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
final int target = view.getMeasuredHeight();
Log.d(AnimHelper.class.getSimpleName(), target+"");
view.getLayoutParams().height = 1;
view.setVisibility(View.VISIBLE);
Animation anim = new Animation()
{
@Override
protected void applyTransformation(float time, Transformation t) {
view.getLayoutParams().height = time == 1
? LinearLayout.LayoutParams.WRAP_CONTENT
: (int)(target * time);
view.requestLayout();
}
@Override
public boolean willChangeBounds() {
return true;
}
};
anim.setDuration((int)(target / view.getContext().getResources().getDisplayMetrics().density));
anim.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
view.invalidate();
if(view instanceof RecyclerView)
((RecyclerView)view).getAdapter().notifyDataSetChanged();
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
anim.setInterpolator(FAST_OUT_LINEAR_IN_INTERPOLATOR);
view.startAnimation(anim);
}
public static void collapse(final View view) {
final int initialHeight = view.getMeasuredHeight();
Animation anim = new Animation()
{
@Override
protected void applyTransformation(float time, Transformation t) {
if(time == 1){
view.setVisibility(View.GONE);
}else{
view.getLayoutParams().height = initialHeight - (int)(initialHeight * time);
view.requestLayout();
}
}
@Override
public boolean willChangeBounds() {
return true;
}
};
anim.setDuration((int)(initialHeight / view.getContext().getResources().getDisplayMetrics().density));
anim.setInterpolator(FAST_OUT_LINEAR_IN_INTERPOLATOR);
view.startAnimation(anim);
}
}