package com.marshalchen.common.uimodule.activityanimation; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Rect; import android.os.Build; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; public class AnimatedDoorLayout extends ViewGroup { private static final String TAG = "AnimatedDoorLayout"; static final boolean IS_JBMR2 = Build.VERSION.SDK_INT == Build.VERSION_CODES.JELLY_BEAN_MR2; public static final int HORIZONTAL_DOOR = 1; public static final int VERTICAL_DOOR = 2; private Rect mRect = new Rect(); private int mOriginalWidth; private int mOriginalHeight; private int mDoorType; private float mProgress; private Bitmap mFullBitmap; public AnimatedDoorLayout(Context context) { super(context); } public AnimatedDoorLayout(Context context, AttributeSet attrs) { super(context, attrs); } public AnimatedDoorLayout(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } public void setDoorType(int doorType) { mDoorType = doorType; } public float getProgress() { return mProgress; } public void setProgress(float progress) { mProgress = progress; invalidate(); } @Override protected boolean addViewInLayout(View child, int index, LayoutParams params, boolean preventRequestLayout) { throwCustomException(getChildCount()); boolean returnValue = super.addViewInLayout(child, index, params, preventRequestLayout); return returnValue; } @Override public void addView(View child, int index, LayoutParams params) { throwCustomException(getChildCount()); super.addView(child, index, params); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { View child = getChildAt(0); measureChild(child, widthMeasureSpec, heightMeasureSpec); setMeasuredDimension(widthMeasureSpec, heightMeasureSpec); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { View child = getChildAt(0); child.layout(0, 0, child.getMeasuredWidth(), child.getMeasuredHeight()); updateDoor(); } private void throwCustomException (int numOfChildViews) { if (numOfChildViews == 1) { throw new IllegalArgumentException("only one child please"); } } private void updateDoor() { prepareDoor(); invalidate(); } private void prepareDoor() { if(isInEditMode()) { return; } mOriginalWidth = getMeasuredWidth(); mOriginalHeight = getMeasuredHeight(); if (IS_JBMR2) { mFullBitmap = Bitmap.createBitmap(mOriginalWidth, mOriginalHeight, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(mFullBitmap); getChildAt(0).draw(canvas); } } @Override protected void dispatchDraw(Canvas canvas) { if(isInEditMode() || mProgress >= 1f) { super.dispatchDraw(canvas); return; } int delta; if(mDoorType == VERTICAL_DOOR) { delta = (int) ((mOriginalHeight/2)*mProgress); } else { delta = (int) ((mOriginalWidth/2)*mProgress); } //1st door canvas.save(); if(mDoorType == VERTICAL_DOOR) { mRect.set(0, 0, mOriginalWidth, delta); } else { mRect.set(0, 0, delta, mOriginalHeight); } if (IS_JBMR2) { canvas.drawBitmap(mFullBitmap, mRect, mRect, null); } else { canvas.clipRect(mRect); super.dispatchDraw(canvas); } canvas.restore(); //2nd door canvas.save(); if(mDoorType == VERTICAL_DOOR) { mRect.set(0, mOriginalHeight - delta, mOriginalWidth, mOriginalHeight); } else { mRect.set(mOriginalWidth - delta, 0, mOriginalWidth, mOriginalHeight); } if (IS_JBMR2) { canvas.drawBitmap(mFullBitmap, mRect, mRect, null); } else { canvas.clipRect(mRect); super.dispatchDraw(canvas); } canvas.restore(); } }