Andoridプロパティアニメーションによるactivityの切り替え効果
5277 ワード
システムに付属するactivityの切り替え効果は望ましくなく、自分で定義する必要があります.属性アニメーションで実現します.
まず、親Activity:AnimatedDoorActivityを抽象化します.
最後にオープンソースプロジェクトアドレスを添付し、demo apkを添付します.
https://github.com/flavienlaurent/activityanimation
まず、親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