package com.github.andlyticsproject.view; import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.view.animation.AccelerateInterpolator; import android.view.animation.Animation; import android.view.animation.DecelerateInterpolator; import android.view.animation.Animation.AnimationListener; /** * This code was extracted from the Transition3D sample activity found in the Android ApiDemos. The * animation is made of two smaller animations: the first half rotates the list by 90 degrees on the * Y axis and the second half rotates the picture by 90 degrees on the Y axis. When the first half * finishes, the list is made invisible and the picture is set visible. */ public class ViewSwitcher3D { private static final String TAG = "ViewSwitcher"; private ViewGroup mContainer; private View mFrondside; private View mBackside; private long mDuration = 600; private float mDepthOfRotation = 300f; private ViewSwitcherListener listener; public ViewSwitcher3D(ViewGroup container) { mContainer = container; mFrondside = container.getChildAt(0); mBackside = container.getChildAt(1); // Since we are caching large views, we want to keep their cache // between each animation mContainer.setPersistentDrawingCache(ViewGroup.PERSISTENT_ANIMATION_CACHE); } public void setDuration(long duration) { mDuration = duration; } public void swap() { float start, end; if (isFrontsideVisible()) { Log.v(TAG, "turning to the backside!"); start = 0; end = 90; } else { Log.v(TAG, "turning to the frontside!"); start = 180; end = 90; } Rotate3dAnimation rotation = new Rotate3dAnimation(start, end, mContainer.getWidth() / 2.0f, mContainer.getHeight() / 2.0f, mDepthOfRotation, true, getListener()); rotation.setDuration(mDuration / 2); rotation.setFillAfter(true); rotation.setInterpolator(new AccelerateInterpolator()); rotation.setAnimationListener(new TurnAroundListener()); mContainer.startAnimation(rotation); } public boolean isFrontsideVisible() { return mFrondside.getVisibility() == View.VISIBLE; } public boolean isBacksideVisible() { return mBackside.getVisibility() == View.VISIBLE; } /** * Listen for the end of the first half of the animation. Then post a new action that * effectively swaps the views when the container is rotated 90 degrees and thus invisible. */ private final class TurnAroundListener implements Animation.AnimationListener { public void onAnimationStart(Animation animation) { } public void onAnimationEnd(Animation animation) { mContainer.post(new SwapViews()); } public void onAnimationRepeat(Animation animation) { } } /** * Swapping the views and start the second half of the animation. */ private final class SwapViews implements Runnable { public void run() { final float centerX = mContainer.getWidth() / 2.0f; final float centerY = mContainer.getHeight() / 2.0f; Rotate3dAnimation rotation; if (isFrontsideVisible()) { mFrondside.setVisibility(View.GONE); mBackside.setVisibility(View.VISIBLE); unmirrorTheBackside(); mBackside.requestFocus(); rotation = new Rotate3dAnimation(90, 180, centerX, centerY, mDepthOfRotation, false, getListener()); } else { mBackside.setVisibility(View.GONE); mBackside.clearAnimation(); // remove the mirroring mFrondside.setVisibility(View.VISIBLE); mFrondside.requestFocus(); rotation = new Rotate3dAnimation(90, 0, centerX, centerY, mDepthOfRotation, false, getListener()); } rotation.setDuration(mDuration / 2); rotation.setFillAfter(true); rotation.setInterpolator(new DecelerateInterpolator()); rotation.setAnimationListener(new AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationRepeat(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { if (listener != null) { listener.onViewChanged(isFrontsideVisible()); } } }); mContainer.startAnimation(rotation); } } private void unmirrorTheBackside() { Rotate3dAnimation rotation = new Rotate3dAnimation(0, 180, mContainer.getWidth() / 2.0f, mContainer.getHeight() / 2.0f, mDepthOfRotation, false, getListener()); rotation.setDuration(0); rotation.setFillAfter(true); mBackside.startAnimation(rotation); } public void setListener(ViewSwitcherListener listener) { this.listener = listener; } public ViewSwitcherListener getListener() { return listener; } public interface ViewSwitcherListener { public void onViewChanged(boolean frontsideVisible); public void onRender(); } }