Andorid屬性動畫實現activity的切換效果

系統自帶的activity切換效果不盡如人意,需要我們自己定義,我們用屬性動畫來實現。

首先抽象一個父類Activity :AnimatedDoorActivity

public abstract class AnimatedDoorActivity extendsActivity {

private AnimatedDoorLayout mAnimated;

protected int mDoorType;

@Override

protected void onCreate(BundlesavedInstanceState){

super.onCreate(savedInstanceState);

setContentView(layoutResId());

//獲取到根view

FrameLayout activityRoot= (FrameLayout)findViewById(android.R.id.content);

View parent = activityRoot.getChildAt(0);

// 將子類中的layout加到根view

mAnimated = new AnimatedDoorLayout(this);

activityRoot.removeView(parent);

activityRoot.addView(mAnimated,parent.getLayoutParams());

mAnimated.addView(parent);

//動畫類型

mDoorType = getIntent().getIntExtra("door_type",AnimatedDoorLayout.HORIZONTAL_DOOR);

mAnimated.setDoorType(mDoorType);

//將根layout的屬性從get方法獲取到的值(0)在600ms內變爲1

ObjectAnimator animator= ObjectAnimator.ofFloat(mAnimated,ANIMATED_DOOR_LAYOUT_FLOAT_PROPERTY,1).setDuration(600);

animator.start();

}
protected abstract intlayoutResId();

@Override

public void onBackPressed(){

ObjectAnimator animator= ObjectAnimator.ofFloat(mAnimated,ANIMATED_DOOR_LAYOUT_FLOAT_PROPERTY,0).setDuration(600);

animator.addListener(newAnimatorListenerAdapter(){

@Override

public void onAnimationEnd(Animatoranimation){

finish();}
});

animator.start();
}
private static final Property<AnimatedDoorLayout,Float>ANIMATED_DOOR_LAYOUT_FLOAT_PROPERTY =

new Property<AnimatedDoorLayout,Float>(Float.class,"ANIMATED_DOOR_LAYOUT_FLOAT_PROPERTY"){

@Override

public void set(AnimatedDoorLayoutlayout,Float value){

layout.setProgress(value);
}

@Override
public Float get(AnimatedDoorLayoutlayout){
return layout.getProgress();
}
};

@Override

public void finish(){
super.finish();
overridePendingTransition(0,0);
}
}
接下來就是主要工作的類,實際上個是Viewgroup
public class AnimatedDoorLayoutextends ViewGroup {
private static final String TAG = "AnimatedDoorLayout";
static final booleanIS_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(Contextcontext){

super(context);
}
public AnimatedDoorLayout(Contextcontext,AttributeSet attrs){
super(context,attrs);
}

public AnimatedDoorLayout(Contextcontext,AttributeSet attrs,int defStyle) {
super(context,attrs,defStyle);
}

public void setDoorType(intdoorType){
mDoorType = doorType;
}

public float getProgress(){
return mProgress;
}

public void setProgress(floatprogress){//屬性動畫更新該 Viewgroup的屬性值 然後刷新界面
mProgress = progress;
invalidate();
}

@Override
protected boolean addViewInLayout(Viewchild,int index, LayoutParams params,boolean preventRequestLayout) {
throwCustomException(getChildCount());
boolean returnValue = super.addViewInLayout(child,index,params,preventRequestLayout);
return returnValue;
}

@Override
public void addView(Viewchild,int index, LayoutParams params){
throwCustomException(getChildCount());
super.addView(child,index,params);
}

@Override
protected void onMeasure(intwidthMeasureSpec,int heightMeasureSpec) {
View child = getChildAt(0);
measureChild(child,widthMeasureSpec,heightMeasureSpec);
setMeasuredDimension(widthMeasureSpec,heightMeasureSpec);
}

@Override
protected void onLayout(booleanchanged,int l, int t,int r, int b){
View child = getChildAt(0);
child.layout(0,0,child.getMeasuredWidth(),child.getMeasuredHeight());
updateDoor();
}

private void throwCustomException(intnumOfChildViews){
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){//首次將整個 用戶的layout繪製到屏幕上
mFullBitmap = Bitmap.createBitmap(mOriginalWidth,mOriginalHeight,Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(mFullBitmap);
getChildAt(0).draw(canvas);
}
}
@Override
protected void dispatchDraw(Canvascanvas){//刷新,該動畫效果類似開門,分爲垂直和水平開門
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){//根據屬性值計算要截取bitmap的區域 left、top、right、buttom
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();
}
}


最後附上開源項目地址,內有demo apk

https://github.com/flavienlaurent/activityanimation

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章