package com.datdo.mobilib.carrier; import junit.framework.Assert; import android.annotation.SuppressLint; import android.content.Context; import android.os.Build; import android.view.Gravity; import android.view.View; import android.widget.FrameLayout; import com.datdo.mobilib.util.MblUtils; import com.nineoldandroids.animation.Animator; import com.nineoldandroids.animation.Animator.AnimatorListener; import com.nineoldandroids.animation.ValueAnimator; import com.nineoldandroids.animation.ValueAnimator.AnimatorUpdateListener; /** * <pre> * An implementation of {@link com.datdo.mobilib.carrier.MblCarrier} with sliding animation when navigatings betweens interceptor. * 4 direction: LeftRight, RightLeft, TopBottom, BottomTop. * Default direction is LeftRight. * The animation works on all Android API >= 10 * </pre> */ @SuppressLint("RtlHardcoded") public class MblSlidingCarrier extends MblCarrier { /** * Contructor * @see com.datdo.mobilib.carrier.MblCarrier#MblCarrier(android.content.Context, android.widget.FrameLayout, com.datdo.mobilib.carrier.MblCarrier.MblCarrierCallback) */ public MblSlidingCarrier(Context context, FrameLayout interceptorContainerView, MblCarrierCallback callback) { super(context, interceptorContainerView, callback); } /** * Sliding direction */ public static enum SlidingDirection { LEFT_RIGHT, RIGHT_LEFT, TOP_BOTTOM, BOTTOM_TOP; } private SlidingDirection mSlidingDirection = SlidingDirection.LEFT_RIGHT; /** * Get direction to animate. */ public SlidingDirection getSlidingDirection() { return mSlidingDirection; } /** * Set direction to animate. */ public void setSlidingDirection(SlidingDirection slidingOrientation) { Assert.assertNotNull(slidingOrientation); mSlidingDirection = slidingOrientation; } private void animate( final MblInterceptor currentInterceptor, final MblInterceptor nextInterceptor, final int from, final int to, final Runnable onAnimationEnd) { ValueAnimator anim = ValueAnimator.ofInt(from, to); anim.addUpdateListener(new AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator anim) { int val = (Integer) anim.getAnimatedValue(); if (mSlidingDirection == SlidingDirection.LEFT_RIGHT || mSlidingDirection == SlidingDirection.RIGHT_LEFT) { setX(currentInterceptor, val); setX(nextInterceptor, val - to); } else if (mSlidingDirection == SlidingDirection.TOP_BOTTOM || mSlidingDirection == SlidingDirection.BOTTOM_TOP) { setY(currentInterceptor, val); setY(nextInterceptor, val - to); } // prevent blinking if (Math.abs(val - from) >= MblUtils.pxFromDp(10)) { nextInterceptor.setVisibility(View.VISIBLE); } else { nextInterceptor.setVisibility(View.INVISIBLE); } } }); anim.addListener(new AnimatorListener() { @Override public void onAnimationCancel(Animator animation) { onAnimationEnd.run(); } @Override public void onAnimationRepeat(Animator animation) {} @Override public void onAnimationStart(Animator animation) {} @Override public void onAnimationEnd(Animator animation) { onAnimationEnd.run(); } }); anim.setDuration(300); anim.start(); } @Override protected void animateForStarting( final MblInterceptor currentInterceptor, final MblInterceptor nextInterceptor, final Runnable onAnimationEnd) { final int from = 0; final int to; switch (mSlidingDirection) { case LEFT_RIGHT: to = mInterceptorContainerView.getWidth(); break; case RIGHT_LEFT: to = -mInterceptorContainerView.getWidth(); break; case TOP_BOTTOM: to = mInterceptorContainerView.getHeight(); break; case BOTTOM_TOP: to = -mInterceptorContainerView.getHeight(); break; default: return; // never happen } animate(currentInterceptor, nextInterceptor, from, to, onAnimationEnd); } @Override protected void animateForFinishing( final MblInterceptor currentInterceptor, final MblInterceptor previousInterceptor, final Runnable onAnimationEnd) { final int from = 0; final int to; switch (mSlidingDirection) { case LEFT_RIGHT: to = -mInterceptorContainerView.getWidth(); break; case RIGHT_LEFT: to = mInterceptorContainerView.getWidth(); break; case TOP_BOTTOM: to = -mInterceptorContainerView.getHeight(); break; case BOTTOM_TOP: to = mInterceptorContainerView.getHeight(); break; default: return; // never happen } animate(currentInterceptor, previousInterceptor, from, to, onAnimationEnd); } @SuppressLint("NewApi") private void setX(View view, int x) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { view.setLeft(x); } else { FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) view.getLayoutParams(); lp.leftMargin = x; lp.rightMargin = -x; lp.gravity = Gravity.TOP | Gravity.LEFT; view.setLayoutParams(lp); } } @SuppressLint("NewApi") private void setY(View view, int y) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { view.setTop(y); } else { FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) view.getLayoutParams(); lp.topMargin = y; lp.bottomMargin = -y; lp.gravity = Gravity.TOP | Gravity.LEFT; view.setLayoutParams(lp); } } }