package yellow5a5.actswitchanimtool; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.util.AttributeSet; import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.view.ViewTreeObserver; /** * Created by Yellow5A5 on 16/9/16. */ public class ActSwitchAnimTool { public final static int ANIM_DURATION = 700; public final static int MODE_UNINIT = -1; public final static int MODE_SPREAD = 0; public final static int MODE_SHRINK = 1; private final String TRANSFORMER_COLOR_END = "ACT_SWITCH_ANIM_COLOR_END"; private final String TRANSFORMER_TARGET_LOCATION = "ACT_SWITCH_ANIM_TARGET_LOCATION"; private ViewGroup mDecorView; private SwitchAnimView mSwitchAnimView; private Activity mStartAct; private int mColorStart; private int mColorEnd; private int targetViewWidth; private int targetViewHeight; private int[] targetLocation = new int[2]; private boolean isNeedShrinkBack; private boolean isWaitingResume; public ActSwitchAnimTool(Activity activity) { mStartAct = activity; mSwitchAnimView = new SwitchAnimView(mStartAct); mDecorView = (ViewGroup) mStartAct.getWindow().getDecorView(); } public ActSwitchAnimTool startActivity(final Intent intent, final boolean isNeedFinish) { intent.putExtra(TRANSFORMER_TARGET_LOCATION, targetLocation); intent.putExtra(TRANSFORMER_COLOR_END, mColorEnd); mSwitchAnimView.setSwitchAnimCallback(new SwitchAnimCallback() { @Override public void onAnimationStart() { switch (mSwitchAnimView.getmAnimType()) { case MODE_SPREAD: mSwitchAnimView.setClickable(true); break; case MODE_SHRINK: mSwitchAnimView.setClickable(false); break; } } @Override public void onAnimationEnd() { switch (mSwitchAnimView.getmAnimType()) { case MODE_SPREAD: mStartAct.startActivity(intent); if (isNeedFinish == true) { mStartAct.finish(); } else { mDecorView.postDelayed(new Runnable() { @Override public void run() { //if you need turn back by shrinking~ you need add~ if (isNeedShrinkBack == false) { mSwitchAnimView.resetAnimParam(); mDecorView.removeView(mSwitchAnimView); } else { isWaitingResume = true; } } }, 200); } break; case MODE_SHRINK: break; } } @Override public void onAnimationUpdate(int progress) { /* Maybe you want change the alpha of Target-View ~~. if (mTargetView != null){ mTargetView.setAlpha((float) (1 - progress / 100.0f)); } */ } }); return this; } public ActSwitchAnimTool receiveIntent(Intent intent) { targetLocation = intent.getIntArrayExtra(TRANSFORMER_TARGET_LOCATION); mColorEnd = intent.getIntExtra(TRANSFORMER_COLOR_END, Color.BLUE); setmColorEnd(mColorEnd); return this; } public ActSwitchAnimTool target(final View view) { final ViewGroup.LayoutParams bgParams = new ViewGroup.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); //background image. mDecorView.addView(mSwitchAnimView, bgParams); view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { view.getLocationInWindow(targetLocation); targetViewWidth = view.getWidth(); targetViewHeight = view.getHeight(); int circleRadius = (targetViewHeight > targetViewWidth ? targetViewWidth : targetViewHeight) / 2; mSwitchAnimView.setmTargetCircleRadius(circleRadius); mSwitchAnimView.setCenter(targetLocation[0] + targetViewWidth / 2, targetLocation[1] + targetViewHeight / 2); } }); return this; } public ActSwitchAnimTool setCustomEndCallBack(SwitchAnimCallback callback) { mSwitchAnimView.setSwitchAnimCallback(callback); return this; } public ActSwitchAnimTool addContainerView(final View view, final SwitchAnimCallback callback) { mSwitchAnimView.setSwitchAnimCallback(new SwitchAnimCallback() { @Override public void onAnimationStart() { switch (mSwitchAnimView.getmAnimType()) { case MODE_SPREAD: mSwitchAnimView.setClickable(true); break; case MODE_SHRINK: mSwitchAnimView.setClickable(false); break; } } @Override public void onAnimationEnd() { if (view.getParent() != null) return; final ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); switch (mSwitchAnimView.getmAnimType()) { case MODE_SPREAD: mDecorView.addView(view); callback.onAnimationEnd(); break; case MODE_SHRINK: mSwitchAnimView.setSwitchAnimCallback(null); break; } } @Override public void onAnimationUpdate(int progress) { callback.onAnimationUpdate(progress); } }); return this; } public ActSwitchAnimTool removeContainerView(View view) { if (mDecorView != null && view != null) { mDecorView.removeView(view); } return this; } public void build() { if (mSwitchAnimView.getmAnimType() == MODE_SPREAD) { mSwitchAnimView.startSpreadAnim(); } else if (mSwitchAnimView.getmAnimType() == MODE_SHRINK) { mSwitchAnimView.startShrinkAnim(); } } public ActSwitchAnimTool setAnimType(int type) { mSwitchAnimView.setmAnimType(type); return this; } public ActSwitchAnimTool setmColorStart(int color) { mColorStart = color; mSwitchAnimView.setmSpreadColor(color); return this; } public ActSwitchAnimTool setmColorEnd(int color) { mColorEnd = color; mSwitchAnimView.setmShrinkColor(color); return this; } public ActSwitchAnimTool setShrinkBack(boolean isShrinkBack) { isNeedShrinkBack = isShrinkBack; return this; } public boolean isShrinkBack() { return isNeedShrinkBack; } public boolean isWaitingResume() { return isWaitingResume; } public ActSwitchAnimTool setIsWaitingResume(boolean isWaitingResume) { this.isWaitingResume = isWaitingResume; return this; } public int getTargetViewWidth() { return targetViewWidth; } public void setTargetViewWidth(int targetViewWidth) { this.targetViewWidth = targetViewWidth; } public int getTargetViewHeight() { return targetViewHeight; } public void setTargetViewHeight(int targetViewHeight) { this.targetViewHeight = targetViewHeight; } public interface SwitchAnimCallback { void onAnimationStart(); void onAnimationEnd(); void onAnimationUpdate(int progress); } public class SwitchAnimView extends View { private int mCenterX; private int mCenterY; private int mSpreadColor; private int mShrinkColor; private int mAnimType; private int mRadius; private int mDuration; private Paint mSpreadPaint; private Paint mShrinkPaint; private ValueAnimator mAnimator; private int mTargetCircleRadius; private int mScreenLength; private boolean isAnimationReady = false; private SwitchAnimCallback mSwitchAnimCallback; public void setSwitchAnimCallback(SwitchAnimCallback callback) { mSwitchAnimCallback = callback; } public SwitchAnimView(Context context) { this(context, null); } public SwitchAnimView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public SwitchAnimView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(); initAnimation(); } private void init() { mAnimType = MODE_UNINIT; mSpreadPaint = new Paint(); mSpreadPaint.setStrokeWidth(1); mSpreadPaint.setStyle(Paint.Style.STROKE); mSpreadPaint.setColor(Color.BLUE); mShrinkPaint = new Paint(); mShrinkPaint.setStrokeWidth(1); mShrinkPaint.setStyle(Paint.Style.STROKE); mShrinkPaint.setColor(Color.BLUE); mDuration = ANIM_DURATION; mScreenLength = (int) Math.sqrt(Math.pow(getResources().getDisplayMetrics().heightPixels, 2) + Math.pow(getResources().getDisplayMetrics().widthPixels, 2)); } public void resetAnimParam() { mAnimType = -1; mRadius = 0; mSpreadPaint.setStrokeWidth(mRadius); mShrinkPaint.setStrokeWidth(mRadius); invalidate(); } private void initAnimation() { isAnimationReady = true; mAnimator = ValueAnimator.ofInt(0, mScreenLength); mAnimator.setDuration(mDuration); mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { int lastFactor = 0; @Override public void onAnimationUpdate(ValueAnimator animation) { int factor = (int) animation.getAnimatedValue(); mRadius = factor; invalidate(); if (mSwitchAnimCallback != null && lastFactor != factor) { mSwitchAnimCallback.onAnimationUpdate(factor * 100 / mScreenLength); lastFactor = factor; } } }); mAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationStart(Animator animation) { if (mSwitchAnimCallback != null) { mSwitchAnimCallback.onAnimationStart(); if(mAnimType == MODE_SPREAD) { setVisibility(VISIBLE); } } } @Override public void onAnimationEnd(Animator animation) { if (mSwitchAnimCallback != null) { mSwitchAnimCallback.onAnimationEnd(); if(mAnimType == MODE_SHRINK) { setVisibility(GONE); } } } }); } private void startSpreadAnim() { mAnimator.start(); } private void startShrinkAnim() { mAnimator.reverse(); } public void setCenter(int centerX, int centerY) { mCenterX = centerX; mCenterY = centerY; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if (getmAnimType() == MODE_UNINIT) { return; } if (!isAnimationReady) { initAnimation(); } switch (getmAnimType()) { case MODE_SPREAD: mSpreadPaint.setStrokeWidth(mRadius); canvas.drawCircle(mCenterX, mCenterY, mRadius / 2 + mTargetCircleRadius, mSpreadPaint); break; case MODE_SHRINK: mShrinkPaint.setStrokeWidth(mRadius); canvas.drawCircle(mCenterX, mCenterY, mRadius / 2 + mTargetCircleRadius, mShrinkPaint); break; } } private void setAlpha(int alpha) { mSpreadPaint.setAlpha(alpha); mShrinkPaint.setAlpha(alpha); } public int getmRadius() { return mRadius; } public void setmRadius(int mRadius) { this.mRadius = mRadius; } public int getmDuration() { return mDuration; } public void setmDuration(int mDuration) { this.mDuration = mDuration; isAnimationReady = false; } public int getmSpreadColor() { return mSpreadColor; } public void setmSpreadColor(int color) { mSpreadPaint.setColor(color); this.mSpreadColor = color; } public int getmShrinkColor() { return mShrinkColor; } public void setmShrinkColor(int color) { mShrinkPaint.setColor(color); this.mShrinkColor = color; } public int getmAnimType() { return mAnimType; } public void setmAnimType(int mAnimType) { this.mAnimType = mAnimType; } public int getmTargetCircleRadius() { return mTargetCircleRadius; } public void setmTargetCircleRadius(int mTargetCircleRadius) { this.mTargetCircleRadius = mTargetCircleRadius; } } }