Android动画:转场动画(过度动画) ActivityOptionsCompat

2017年7月15日16:54:08 发表评论

简介

Actiivty转场动画可以使用overridePendingTransition (int enterAnim, int exitAnim),但这种方式太老了,接下来介绍另一种方式ActivityOptions,和兼容类(V4)ActivityOptionsCompat

总效果图

这里写图片描述

4个静态方法

这里写图片描述

makeCustomAnimation(Context context, int enterResId, int exitResId)
makeScaleUpAnimation(View source, int startX, int startY, int startWidth, int startHeight)
makeSceneTransitionAnimation(Activity activity, View sharedElement, String sharedElementName)
makeThumbnailScaleUpAnimation(View source, Bitmap thumbnail, int startX, int startY)
makeSceneTransitionAnimation(Activity activity, Pair...<View, String> sharedElements)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

1 makeCustomAnimation(…)

效果图

这里写图片描述

Demo

View是Button

ActivityOptionsCompat options2 = ActivityOptionsCompat.makeScaleUpAnimation(view, view.getWidth() / 2, view.getHeight() / 2, 1000, 1000);
ActivityCompat.startActivity(context, new Intent(context, Activity_I.class), options2.toBundle());

2 makeScaleUpAnimation(…)

效果图

这里写图片描述

Demo

View是Button

ActivityOptionsCompat options2 = ActivityOptionsCompat.makeScaleUpAnimation(view, view.getWidth() / 2, view.getHeight() / 2, 1000, 1000);
ActivityCompat.startActivity(context, new Intent(context, Activity_I.class), options2.toBundle());

bnailScaleUpAnimation(…)

效果图

这里写图片描述

Demo

View是Button

ActivityOptionsCompat options3 = ActivityOptionsCompat.makeThumbnailScaleUpAnimation(view, BitmapFactory.decodeResource(getResources(), R.mipmap.b), 0, 0);
ActivityCompat.startActivity(context, new Intent(context, Activity_I.class), options3.toBundle());

4 makeClipRevealAnimation(…)

效果图

这里写图片描述

Demo

View是Button

ActivityOptionsCompat options4 = ActivityOptionsCompat.makeClipRevealAnimation(view, view.getWidth() / 2, view.getHeight() / 2, 1000, 1000);
ActivityCompat.startActivity(context, new Intent(context, Activity_I.class), options4.toBundle());

transitionName

效果图

这里写图片描述

Demo

View是Button

ActivityOptionsCompat options5 = ActivityOptionsCompat.makeSceneTransitionAnimation(MainActivity.this, iv, "options5");
ActivityCompat.startActivity(context, new Intent(context, Activity_A.class), options5.toBundle());

//多个view
ActivityOptionsCompat activityOptions = ActivityOptionsCompat.makeSceneTransitionAnimation(this, new Pair<View, String>(iv1, "iv1"), new Pair<View, String>(iv2), "iv2");

在Actiivty_A中设置transitionName

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_a);
    context = this;

    iv_a = (ImageView) findViewById(R.id.iv_a);
    //也可以在xml中配置
//        ViewCompat.setTransitionName(iv_a,"options5");
}

XML中设置transitionName

<ImageView
    android:id="@+id/iv_a"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:transitionName="options5"
    android:src="@mipmap/b"/>

6 makeSceneTransitionAnimation(…) Transition

注意:

API>=21

//退出时使用
getWindow().setExitTransition(explode);
//第一次进入时使用
getWindow().setEnterTransition(explode);
//再次进入时使用
getWindow().setReenterTransition(explode);

当然,你也可以在style中配置

当前页是A,点击A页面的Button,打开B,在按back键,回到A.整个过程中,windowEnterTransition是B要执行的动画,windowExitTransition是A要退出的页面的动画。按back键,B退出是有退出动画的,不需要在设置。

<item name="android:windowEnterTransition">@android:transition/slide_left</item>
<item name="android:windowExitTransition">@android:transition/slide_right</item>

注意:是windowEnterTransition,不是windowEnterAnimation

<item name="android:windowEnterAnimation">@android:anim/slide_in_left</item>
<item name="android:windowExitAnimation">@android:anim/slide_out_right</item>

多个view的都需要这样的效果

ActivityOptionsCompat activityOptions = ActivityOptionsCompat.makeSceneTransitionAnimation(
        this,
        new Pair<View, String>(view.findViewById(R.id.imageview_item),
                DetailActivity.VIEW_NAME_HEADER_IMAGE),
        new Pair<View, String>(view.findViewById(R.id.textview_name),
                DetailActivity.VIEW_NAME_HEADER_TITLE));
ViewCompat.setTransitionName(mHeaderImageView, VIEW_NAME_HEADER_IMAGE);
ViewCompat.setTransitionName(mHeaderTitle, VIEW_NAME_HEADER_TITLE);

6-1 explode

效果图

这里写图片描述

Demo

View是Button

ActivityOptionsCompat options6 = ActivityOptionsCompat.makeSceneTransitionAnimation(MainActivity.this);
ActivityCompat.startActivity(context, new Intent(context, Activity_B.class), options6.toBundle());

需要在被开启的activity中设置

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // 设置contentFeature,可使用切换动画
    // getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);  或者
    requestWindowFeature(Window.FEATURE_CONTENT_TRANSITIONS);
    Transition explode = TransitionInflater.from(this).inflateTransition(android.R.transition.explode);
    getWindow().setEnterTransition(explode);

    setContentView(R.layout.activity_b);
}

可以给transition添加监听

explode.addListener(transitionListener);

private Transition.TransitionListener transitionListener = new Transition.TransitionListener() {
   @Override
    public void onTransitionStart(Transition transition) {

    }

    @Override
    public void onTransitionEnd(Transition transition) {
        loginApp();
    }

    @Override
    public void onTransitionCancel(Transition transition) {

    }

    @Override
    public void onTransitionPause(Transition transition) {

    }

    @Override
    public void onTransitionResume(Transition transition) {

    }
};

6-2 fade

效果图

这里写图片描述

demo

View是Button

ActivityOptionsCompat options6 = ActivityOptionsCompat.makeSceneTransitionAnimation(MainActivity.this);
ActivityCompat.startActivity(context, new Intent(context, Activity_C.class), options6.toBundle());

需要在被开启的activity中设置

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
    Transition fade = TransitionInflater.from(this).inflateTransition(android.R.transition.fade);
    getWindow().setEnterTransition(fade);

    setContentView(R.layout.activity_b);
}

6-3 move

效果图

这里写图片描述

Demo

View是Button

ActivityOptionsCompat options6 = ActivityOptionsCompat.makeSceneTransitionAnimation(MainActivity.this);
ActivityCompat.startActivity(context, new Intent(context, Activity_D.class), options6.toBundle());

需要在被开启的activity中设置

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
    Transition move = TransitionInflater.from(this).inflateTransition(android.R.transition.move);
    getWindow().setEnterTransition(move);

    setContentView(R.layout.activity_b);
}

6-4 slide_bottom

效果图

这里写图片描述

Demo

View是Button

ActivityOptionsCompat options6 = ActivityOptionsCompat.makeSceneTransitionAnimation(MainActivity.this);
ActivityCompat.startActivity(context, new Intent(context, Activity_E.class), options6.toBundle());

Activity_E 需要在被开启的activity中设置

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
    Transition slide_bottom = TransitionInflater.from(this).inflateTransition(android.R.transition.slide_bottom);
    getWindow().setEnterTransition(slide_bottom);

    setContentView(R.layout.activity_b);
}

6-5 slide_right

效果图

这里写图片描述

Demo

View是Button

ActivityOptionsCompat options10 = ActivityOptionsCompat.makeSceneTransitionAnimation(MainActivity.this);
ActivityCompat.startActivity(context, new Intent(context, Activity_F.class), options10.toBundle());

需要在被开启的activity中设置

public class Activity_F extends AppCompatActivity {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
        Transition slide_right = TransitionInflater.from(this).inflateTransition(android.R.transition.slide_right);
        getWindow().setEnterTransition(slide_right);

        setContentView(R.layout.activity_b);
    }
}

6-6 slide_top

效果图

这里写图片描述

Demo

View是Button

ActivityOptionsCompat options11 = ActivityOptionsCompat.makeSceneTransitionAnimation(MainActivity.this);
ActivityCompat.startActivity(context, new Intent(context, Activity_G.class), options11.toBundle());

需要在被开启的activity中设置

public class Activity_G extends AppCompatActivity {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
        Transition slide_top = TransitionInflater.from(this).inflateTransition(android.R.transition.slide_top);
        getWindow().setEnterTransition(slide_top);

        setContentView(R.layout.activity_b);
    }
}

6-7 slide_left

效果图

这里写图片描述

Demo

View是Button

ActivityOptionsCompat options12 = ActivityOptionsCompat.makeSceneTransitionAnimation(MainActivity.this);
ActivityCompat.startActivity(context, new Intent(context, Activity_H.class), options12.toBundle());

需要在被开启的activity中设置

public class Activity_H extends AppCompatActivity {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
        Transition slide_left = TransitionInflater.from(this).inflateTransition(android.R.transition.slide_left);
        getWindow().setEnterTransition(slide_left);

        setContentView(R.layout.activity_b);
    }
}
  • 1

其他

优雅的退出

由A进到到B,我们使用的是转场动画,在B页面,如果按back键,B页面的退出也是转场动画,但是通常Activity顶部有个Titlte,左侧是返回箭头,那么怎么让B退出的时候像进入时那样使用转场东动画呢?
解决方法就是在我们给箭头icon设置点击事件,在点击中调用方法onBackPressed();
这里写图片描述

ic_back.setNavigationOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        onBackPressed();
    }
});

源码

点击下载源码:ActivityOptionCompat01

overridePendingTransition (int enterAnim, int exitAnim)

overridePendingTransition(R.anim.bottom_to_current,R.anim.current_to_top);

当前页向上退出

这里写图片描述
current_to_top.xml

<?xml version="1.0" encoding="utf-8"?>
<translate
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="500"
    android:fromYDelta="0"
    android:toYDelta="-100%">
</translate>

bottom_to_current.xml

<?xml version="1.0" encoding="utf-8"?>
<translate
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromYDelta="100%"
    android:duration="500"
    android:toYDelta="0">
</translate>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

当前页向下退出

这里写图片描述
current_to_bottom.xml

<?xml version="1.0" encoding="utf-8"?>
<translate
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="500"
    android:fromYDelta="0"
    android:toYDelta="100%">
</translate>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

top_to_current.xml

<?xml version="1.0" encoding="utf-8"?>
<translate
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="500"
    android:fromYDelta="-100%"
    android:toYDelta="0">
</translate>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

当前页向右退出

这里写图片描述
current_to_right.xml

<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromXDelta="0"
    android:toXDelta="100%"
    android:duration="500" >
</translate>
<!-- 要使用%,这样才有效果,反则没有效果,500ms不起作用 -->
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

left_to_current.xml

<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromXDelta="-100%"
    android:toXDelta="0"
    android:duration="500" >
</translate>
<!-- 要使用%,这样才有效果,反则没有效果,500ms不起作用 -->
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

当前页向左退出

这里写图片描述
current_to_left.xml

<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromXDelta="0"
    android:toXDelta="-100%"
    android:duration="500" >
</translate>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

right_to_current.xml

<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromXDelta="100%"
    android:toXDelta="0"
    android:duration="500" >
</translate>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

Activity切换时黑屏

如果我们采用这种方式那么会导致当前页黑屏

startActivity(new Intent(Activity_A.this,Activity_C.class));
overridePendingTransition(R.anim.right_to_current,0);
  • 1
  • 2
  • 1
  • 2

见图:
这里写图片描述
解决方法:不实用0,仍然使用动画,将退出动画设置透明度从1到1.
current_stay_alpha.xml

R.anim.current_stay_alpha

overridePendingTransition(R.anim.right_to_current,R.anim.current_stay_alpha);
  • 1
  • 1
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
       android:duration="500"
       android:fromAlpha="1"
       android:toAlpha="1">
</alpha>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

当然,不只是current_stay_alpha,只要使当前页保持不动都可以,下面还有

R.anim.current_stay_translate

overridePendingTransition(R.anim.right_to_current,R.anim.current_stay_translate);
  • 1
  • 1
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
           android:fromXDelta="0"
           android:toXDelta="0"
           android:duration="500">
</translate>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

current_stay_scale.xml

overridePendingTransition(R.anim.right_to_current,R.anim.current_stay_scale)
  • 1
  • 1
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
       android:duration="500"
       android:fromXScale="1"
       android:fromYScale="1"
       android:toXScale="1"
       android:toYScale="1">
</scale>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
Android动画:转场动画(过度动画) ActivityOptionsCompat
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

current_stay_rotate.xml

overridePendingTransition(R.anim.right_to_current,R.anim.current_stay_rotate)
  • 1
  • 1
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
       android:duration="500">
</rotate>