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