package com.marshalchen.common.uimodule.easyandroidanimations; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.animation.TimeInterpolator; import android.view.View; import android.view.ViewGroup; import android.view.animation.AccelerateDecelerateInterpolator; /** * This animation causes the view to flip horizontally to reveal another * user-provided view at the back of the original view. On animation end, the * original view is restored to its original state and is set to * <code>View.INVISIBLE</code>. * * @author SiYao * */ public class FlipHorizontalToAnimation extends Animation { public static final int PIVOT_CENTER = 0, PIVOT_LEFT = 1, PIVOT_RIGHT = 2; View flipToView; int pivot, direction; TimeInterpolator interpolator; long duration; AnimationListener listener; /** * This animation causes the view to flip horizontally to reveal another * user-provided view at the back of the original view. On animation end, * the original view is restored to its original state and is set to * <code>View.INVISIBLE</code>. * * @param view * The view to be animated. */ public FlipHorizontalToAnimation(View view) { this.view = view; flipToView = null; pivot = PIVOT_CENTER; direction = DIRECTION_RIGHT; interpolator = new AccelerateDecelerateInterpolator(); duration = DURATION_LONG; listener = null; } @Override public void animate() { ViewGroup parentView = (ViewGroup) view.getParent(), rootView = (ViewGroup) view .getRootView(); float pivotX, pivotY, flipAngle = 270f, viewWidth = view.getWidth(), viewHeight = view .getHeight(); final float originalRotationY = view.getRotationY(); switch (pivot) { case PIVOT_LEFT: pivotX = 0f; pivotY = viewHeight / 2; break; case PIVOT_RIGHT: pivotX = viewWidth; pivotY = viewHeight / 2; break; default: pivotX = viewWidth / 2; pivotY = viewHeight / 2; flipAngle = 90f; break; } view.setPivotX(pivotX); view.setPivotY(pivotY); flipToView.setLayoutParams(view.getLayoutParams()); flipToView.setLeft(view.getLeft()); flipToView.setTop(view.getTop()); flipToView.setPivotX(pivotX); flipToView.setPivotY(pivotY); flipToView.setVisibility(View.VISIBLE); while (parentView != rootView) { parentView.setClipChildren(false); parentView = (ViewGroup) parentView.getParent(); } rootView.setClipChildren(false); AnimatorSet flipToAnim = new AnimatorSet(); if (direction == DIRECTION_RIGHT) { flipToView.setRotationY(270f); flipToAnim.playSequentially(ObjectAnimator.ofFloat(view, View.ROTATION_Y, 0f, flipAngle), ObjectAnimator.ofFloat( flipToView, View.ROTATION_Y, 270f, 360f)); } else { flipToView.setRotationY(-270f); flipToAnim.playSequentially(ObjectAnimator.ofFloat(view, View.ROTATION_Y, 0f, -flipAngle), ObjectAnimator.ofFloat( flipToView, View.ROTATION_Y, -270f, -360f)); } flipToAnim.setInterpolator(interpolator); flipToAnim.setDuration(duration / 2); flipToAnim.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { view.setVisibility(View.INVISIBLE); view.setRotationY(originalRotationY); if (getListener() != null) { getListener() .onAnimationEnd(FlipHorizontalToAnimation.this); } } }); flipToAnim.start(); } /** * @return The view to be revealed after flipping the original view. */ public View getFlipToView() { return flipToView; } /** * @param flipToView * The view to set to be revealed after flipping the original * view. * @return This object, allowing calls to methods in this class to be * chained. */ public FlipHorizontalToAnimation setFlipToView(View flipToView) { this.flipToView = flipToView; return this; } /** * The available pivot points to flip are <code>PIVOT_CENTER</code>, * <code>PIVOT_LEFT</code> and <code>PIVOT_RIGHT</code>. * * @return The pivot point for flipping. */ public int getPivot() { return pivot; } /** * The available pivot points to flip are <code>PIVOT_CENTER</code>, * <code>PIVOT_LEFT</code> and <code>PIVOT_RIGHT</code>. * * @param pivot * The pivot point to set for flipping. * @return This object, allowing calls to methods in this class to be * chained. */ public FlipHorizontalToAnimation setPivot(int pivot) { this.pivot = pivot; return this; } /** * The available flip directions are <code>DIRECTION_LEFT</code> and * <code>DIRECTION_RIGHT</code>. * * @return The direction of the flip. * @see Animation */ public int getDirection() { return direction; } /** * The available flip directions are <code>DIRECTION_LEFT</code> and * <code>DIRECTION_RIGHT</code>. * * @param direction * The direction of the flip to set. * @return This object, allowing calls to methods in this class to be * chained. * @see Animation */ public FlipHorizontalToAnimation setDirection(int direction) { this.direction = direction; return this; } /** * @return The interpolator of the entire animation. */ public TimeInterpolator getInterpolator() { return interpolator; } /** * @param interpolator * The interpolator of the entire animation to set. */ public FlipHorizontalToAnimation setInterpolator( TimeInterpolator interpolator) { this.interpolator = interpolator; return this; } /** * @return The duration of the entire animation. */ public long getDuration() { return duration; } /** * @param duration * The duration of the entire animation to set. * @return This object, allowing calls to methods in this class to be * chained. */ public FlipHorizontalToAnimation setDuration(long duration) { this.duration = duration; return this; } /** * @return The listener for the end of the animation. */ public AnimationListener getListener() { return listener; } /** * @param listener * The listener to set for the end of the animation. * @return This object, allowing calls to methods in this class to be * chained. */ public FlipHorizontalToAnimation setListener(AnimationListener listener) { this.listener = listener; return this; } }