现在的位置: 首页 > 综合 > 正文

Andorid属性动画实现activity的切换效果

2017年09月20日 ⁄ 综合 ⁄ 共 4742字 ⁄ 字号 评论关闭

系统自带的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

抱歉!评论已关闭.