package net.avenwu.support.widget; import android.content.Context; import android.graphics.Camera; import android.graphics.Matrix; import android.util.AttributeSet; 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.Transformation; import android.widget.FrameLayout; /** * Created by aven on 1/19/16. */ public class FlipLayout extends FrameLayout { View mFrontView; View mBackView; boolean isFlipping = false; public FlipLayout(Context context) { this(context, null); } public FlipLayout(Context context, AttributeSet attrs) { super(context, attrs); } @Override public void addView(View child, int index, ViewGroup.LayoutParams params) { if (getChildCount() > 1) { throw new IllegalArgumentException("FlipLayout can only have to child view"); } super.addView(child, index, params); if (mBackView == null) { mBackView = child; } else { mFrontView = child; } } public void setViewOrder(View front, View back) { mFrontView = front; mBackView = back; mFrontView.setVisibility(VISIBLE); mBackView.setVisibility(INVISIBLE); } /** * toggle the flip state */ public void flip() { if (isFlipping) { return; } mBackView.setVisibility(GONE); mFrontView.setVisibility(VISIBLE); final float centerX = mFrontView.getWidth() / 2f; final float centerY = mFrontView.getHeight() / 2f; final FlipAnimation frontViewAnimation = new FlipAnimation(centerX, centerY, true); frontViewAnimation.setDuration(500); frontViewAnimation.setFillAfter(true); frontViewAnimation.setInterpolator(new AccelerateInterpolator()); frontViewAnimation.setAnimationListener(new SimpleAnimationListener() { @Override public void onAnimationEnd(Animation animation) { mBackView.setVisibility(VISIBLE); mFrontView.setVisibility(INVISIBLE); final float centerX = mBackView.getWidth() / 2f; final float centerY = mBackView.getHeight() / 2f; FlipAnimation backViewAnimation = new FlipAnimation(centerX, centerY, false); backViewAnimation.setDuration(500); backViewAnimation.setFillAfter(true); backViewAnimation.setInterpolator(new DecelerateInterpolator()); backViewAnimation.setAnimationListener(new SimpleAnimationListener() { @Override public void onAnimationEnd(Animation animation) { View temp = mFrontView; mFrontView = mBackView; mBackView = temp; isFlipping = false; } }); mBackView.startAnimation(backViewAnimation); } }); mFrontView.startAnimation(frontViewAnimation); isFlipping = true; } private static class FlipAnimation extends Animation { private final float mFrom; private final float mTo; private final float mCenterX; private final float mCenterY; private final float SCALE_DEFAULT = 0.618f; private final float ALPHA_DEFAULT = 0.8f; private Camera mCamera; private boolean mScaleDown; public FlipAnimation(float mCenterX, float mCenterY, boolean scaleDown) { this.mCenterX = mCenterX; this.mCenterY = mCenterY; mScaleDown = scaleDown; if (scaleDown) { this.mFrom = 0; this.mTo = 90; } else { this.mFrom = -90; this.mTo = 0; } } @Override public void initialize(int width, int height, int parentWidth, int parentHeight) { super.initialize(width, height, parentWidth, parentHeight); mCamera = new Camera(); } @Override protected void applyTransformation(float interpolatedTime, Transformation t) { float degree = mFrom + (mTo - mFrom) * interpolatedTime; float scale = mScaleDown ? (1 - (1 - SCALE_DEFAULT) * interpolatedTime) : (SCALE_DEFAULT + (1 - SCALE_DEFAULT) * interpolatedTime); float alpha = mScaleDown ? (1 - (1 - ALPHA_DEFAULT) * interpolatedTime) : (ALPHA_DEFAULT + (1 - ALPHA_DEFAULT) * interpolatedTime); t.setAlpha(alpha); final Matrix matrix = t.getMatrix(); mCamera.save(); mCamera.rotateY(degree); mCamera.getMatrix(matrix); mCamera.restore(); matrix.preTranslate(-mCenterX, -mCenterY); matrix.postTranslate(mCenterX, mCenterY); matrix.preScale(scale, scale, mCenterX, mCenterY); } } private static class SimpleAnimationListener implements Animation.AnimationListener { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { } @Override public void onAnimationRepeat(Animation animation) { } } }