package info.guardianproject.securereaderinterface.uiutil; import info.guardianproject.securereaderinterface.R; import android.animation.Animator; import android.animation.Animator.AnimatorListener; import android.annotation.SuppressLint; import android.os.Build; import android.view.View; import android.view.ViewGroup; import android.view.ViewGroup.MarginLayoutParams; import android.view.ViewPropertyAnimator; import android.view.animation.AlphaAnimation; import android.view.animation.Animation; import android.view.animation.Animation.AnimationListener; import android.view.animation.AnimationSet; import android.view.animation.AnimationUtils; import android.view.animation.RotateAnimation; import android.view.animation.ScaleAnimation; import android.view.animation.TranslateAnimation; @SuppressLint("NewApi") public class AnimationHelpers { public interface FadeInFadeOutListener { void onFadeInStarted(View view); void onFadeInEnded(View view); void onFadeOutStarted(View view); void onFadeOutEnded(View view); } /** * Fade the alpha of the view to 0. * * @param view * The view to fade * @param duration * Number of ms for the animation * @param startDelay * Optional start delay in ms * @param removeFromParent * true to remove the view from parent after animation, false to * just hide it */ public static void fadeOut(final View view, int duration, int startDelay, final boolean removeFromParent) { AnimationHelpers.fadeOut(view, duration, startDelay, removeFromParent, null); } /** * Fade the alpha of the view to 0. * * @param view * The view to fade * @param duration * Number of ms for the animation * @param startDelay * Optional start delay in ms * @param removeFromParent * true to remove the view from parent after animation, false to * just hide it * @param listener * Optional listener to receive animation events */ public static void fadeOut(final View view, int duration, int startDelay, final boolean removeFromParent, final FadeInFadeOutListener listener) { if (Build.VERSION.SDK_INT >= 14) { if (duration == 0 && startDelay == 0) { if (listener != null) listener.onFadeOutStarted(view); view.setAlpha(0); if (removeFromParent) ((ViewGroup) view.getParent()).removeView(view); if (listener != null) listener.onFadeOutEnded(view); } else { view.animate().alpha(0).setDuration(duration).setStartDelay(startDelay).setListener(new AnimatorListener() { @Override public void onAnimationCancel(Animator animation) { view.setVisibility(View.GONE); if (removeFromParent) ((ViewGroup) view.getParent()).removeView(view); } @Override public void onAnimationEnd(Animator animation) { view.setVisibility(View.GONE); if (removeFromParent) ((ViewGroup) view.getParent()).removeView(view); if (listener != null) listener.onFadeOutEnded(view); } @Override public void onAnimationRepeat(Animator animation) { } @Override public void onAnimationStart(Animator animation) { if (listener != null) listener.onFadeOutStarted(view); } }); } } else { AlphaAnimation alpha = new AlphaAnimation((duration == 0) ? 0 : 1.0f, 0); alpha.setDuration(duration); if (startDelay > 0) alpha.setStartTime(AnimationUtils.currentAnimationTimeMillis() + startDelay); alpha.setFillAfter(true); alpha.setAnimationListener(new AnimationListener() { @Override public void onAnimationEnd(Animation animation) { view.setVisibility(View.GONE); if (removeFromParent) ((ViewGroup) view.getParent()).removeView(view); if (listener != null) listener.onFadeOutEnded(view); } @Override public void onAnimationRepeat(Animation animation) { } @Override public void onAnimationStart(Animation animation) { if (listener != null) listener.onFadeOutStarted(view); } }); addAnimation(view, alpha); } } public static void fadeIn(final View view, final int duration, final int fadeOutDelay, final boolean removeFromParent) { AnimationHelpers.fadeIn(view, duration, fadeOutDelay, removeFromParent, null); } public static void fadeIn(final View view, final int duration, final int fadeOutDelay, final boolean removeFromParent, final FadeInFadeOutListener listener) { if (Build.VERSION.SDK_INT >= 14) { view.animate().alpha(1).setDuration(duration).setStartDelay(0).setListener(new AnimatorListener() { @Override public void onAnimationCancel(Animator animation) { } @Override public void onAnimationEnd(Animator animation) { if (listener != null) listener.onFadeInEnded(view); if (fadeOutDelay > 0) fadeOut(view, duration, fadeOutDelay, removeFromParent, listener); } @Override public void onAnimationRepeat(Animator animation) { } @Override public void onAnimationStart(Animator animation) { if (listener != null) listener.onFadeInStarted(view); } }); } else { AlphaAnimation alpha = new AlphaAnimation((duration == 0) ? 1 : 0, 1); alpha.setDuration(duration); alpha.setFillAfter(true); alpha.setAnimationListener(new AnimationListener() { @Override public void onAnimationEnd(Animation animation) { if (listener != null) listener.onFadeInEnded(view); if (fadeOutDelay > 0) fadeOut(view, duration, fadeOutDelay, removeFromParent); } @Override public void onAnimationRepeat(Animation animation) { } @Override public void onAnimationStart(Animation animation) { if (listener != null) listener.onFadeInStarted(view); } }); addAnimation(view, alpha); } } public static void rotate(final View view, float fromDegrees, float toDegrees, long duration) { if (Build.VERSION.SDK_INT >= 12) { if (duration == 0) view.setRotation(toDegrees); else view.animate().rotation(toDegrees).setDuration(duration).start(); } else { RotateAnimation rotate = new RotateAnimation(fromDegrees, toDegrees, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); rotate.setDuration(duration); rotate.setFillEnabled(true); rotate.setFillBefore(true); rotate.setFillAfter(true); addAnimation(view, rotate); } } public static void translateY(final View view, float fromY, float toY, long duration) { if (Build.VERSION.SDK_INT >= 12) { if (duration == 0) view.setTranslationY(toY); else view.animate().translationY(toY).setDuration(duration).start(); } else { TranslateAnimation translate = new TranslateAnimation(0, 0, fromY, toY); translate.setDuration(duration); translate.setFillEnabled(true); translate.setFillBefore(true); translate.setFillAfter(true); addAnimation(view, translate); } } public static void translateX(final View view, float fromX, float toX, long duration) { if (Build.VERSION.SDK_INT >= 12) { if (duration == 0) view.setTranslationX(toX); else view.animate().translationX(toX).setDuration(duration).start(); } else { TranslateAnimation translate = new TranslateAnimation(fromX, toX, 0, 0); translate.setDuration(duration); translate.setFillEnabled(true); translate.setFillBefore(true); translate.setFillAfter(true); addAnimation(view, translate); } } public static void scale(final View view, float fromScale, float toScale, long duration, final Runnable whenDone) { if (Build.VERSION.SDK_INT >= 12) { if (duration == 0) { view.setScaleX(toScale); view.setScaleY(toScale); if (whenDone != null) whenDone.run(); } else { ViewPropertyAnimator animation = view.animate().scaleX(toScale).scaleY(toScale).setDuration(duration); if (whenDone != null) { animation.setListener(new AnimatorListener() { @Override public void onAnimationCancel(Animator animation) { whenDone.run(); } @Override public void onAnimationEnd(Animator animation) { whenDone.run(); } @Override public void onAnimationRepeat(Animator animation) { } @Override public void onAnimationStart(Animator animation) { } }); } animation.start(); } } else { ScaleAnimation scale = new ScaleAnimation(fromScale, toScale, fromScale, toScale, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); scale.setDuration(duration); scale.setFillEnabled(true); scale.setFillBefore(true); scale.setFillAfter(true); if (whenDone != null) { scale.setAnimationListener(new AnimationListener() { @Override public void onAnimationEnd(Animation animation) { whenDone.run(); } @Override public void onAnimationRepeat(Animation animation) { } @Override public void onAnimationStart(Animation animation) { } }); } addAnimation(view, scale); } } public static void addAnimation(View view, Animation animation) { addAnimation(view, animation, false); } public static void addAnimation(View view, Animation animation, boolean first) { Animation previousAnimation = view.getAnimation(); if (previousAnimation == null || previousAnimation.getClass() == animation.getClass()) { if (animation.getStartTime() == Animation.START_ON_FIRST_FRAME) view.startAnimation(animation); else view.setAnimation(animation); return; } if (!(previousAnimation instanceof AnimationSet)) { AnimationSet newSet = new AnimationSet(false); newSet.addAnimation(previousAnimation); previousAnimation = newSet; } // Remove old of same type // AnimationSet set = (AnimationSet) previousAnimation; for (int i = 0; i < set.getAnimations().size(); i++) { Animation anim = set.getAnimations().get(i); if (anim.getClass() == animation.getClass()) { set.getAnimations().remove(i); break; } } // Add this (first if it is a scale animation ,else at end) if (animation instanceof ScaleAnimation || first) { set.getAnimations().add(0, animation); } else { set.getAnimations().add(animation); } animation.startNow(); view.setAnimation(set); } public static void setTranslationX(final View view, int value) { if (Build.VERSION.SDK_INT >= 11) { view.setTranslationX(value); } else { ViewGroup.MarginLayoutParams params = (MarginLayoutParams) view.getLayoutParams(); if (params != null) { ViewGroup.MarginLayoutParams originalParams = (MarginLayoutParams) view.getTag(R.id.compatibility_margin_tag_key); if (originalParams == null) { originalParams = new ViewGroup.MarginLayoutParams(params); view.setTag(R.id.compatibility_margin_tag_key, originalParams); } params.topMargin = originalParams.topMargin; params.leftMargin = originalParams.leftMargin + value; params.bottomMargin = originalParams.bottomMargin; params.rightMargin = originalParams.rightMargin - value; view.setLayoutParams(params); } } } public static void setTranslationY(final View view, int value) { if (Build.VERSION.SDK_INT >= 11) { view.setTranslationY(value); } else { ViewGroup.MarginLayoutParams params = (MarginLayoutParams) view.getLayoutParams(); if (params != null) { ViewGroup.MarginLayoutParams originalParams = (MarginLayoutParams) view.getTag(R.id.compatibility_margin_tag_key); if (originalParams == null) { originalParams = new ViewGroup.MarginLayoutParams(params); view.setTag(R.id.compatibility_margin_tag_key, originalParams); } params.topMargin = originalParams.topMargin + value; params.leftMargin = originalParams.leftMargin; params.bottomMargin = originalParams.bottomMargin - value; params.rightMargin = originalParams.rightMargin; view.setLayoutParams(params); } } } public static int getTranslationX(final View view) { if (Build.VERSION.SDK_INT >= 11) { return (int) view.getTranslationX(); } else { ViewGroup.MarginLayoutParams params = (MarginLayoutParams) view.getLayoutParams(); if (params != null) { ViewGroup.MarginLayoutParams originalParams = (MarginLayoutParams) view.getTag(R.id.compatibility_margin_tag_key); if (originalParams == null) { return 0; } return params.leftMargin - originalParams.leftMargin; } return 0; } } }