1、使用动画启动Activity概述
我们在Android开发应用时,会遇到一个页面跳转到另一个页面的情况,这时候我们如果使用动画过渡会使得页面更加的流畅。
可以看到Android的过渡动画可以在不同状态之间建立视觉联系。您可以为进入和退出过渡,以及 Activity 之间共享元素的过渡指定自定义动画。
2、进入和退出的过渡动画
在Android的官方文档中,我们可以看到在Android 5.0(API)中进入和退出过渡有三种。
1、分解(explode) - 将视图移入场景中心或从中移出。
2、滑动式(slide) -将视图从场景的其中一个边缘移入或移出。
3、淡入淡出式(fade) - 通过更改视图的不透明度,在场景中添加视图或从中移除视图。
以上三种是Android已经定义好的Visibility的子类,我们也可以自定义Visibility的子类来实现过渡,那么我们这里通过以下几个步骤来实现已经定义好三种过渡:
1、在style里将是否使用activity过渡的标志位设为true,或者使用相应处理代码
<style name="BaseAppTheme" parent="Theme.AppCompat.Light">
<item name="android:windowContentTransitions">true</item>
</style>
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState)
getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS)
}
2、设置进入activity和退出activity的过渡方式
(1)在style里设置
<style name="BaseAppTheme" parent="Theme.AppCompat.Light">
<!-- specify enter and exit transitions -->
<item name="android:windowEnterTransition">@transition/activity_explode</item>
<item name="android:windowExitTransition">@transition/activity_fade</item>
</style>
同时在相应的资源文件里应当有相应的transition文件夹
(2)在代码里设置,在MainActivity.java
里
private void setupWindowAnimations() {
Explode explode = (explode) TransitionInflater.from(this).inflateTransition(R.transition.activity_explode);
Fade fade = (fade) TransitionInflater.from(this).inflateTransition(R.transition.activity_fade);
getWindow().setEnterTransition(explode);
getWindow().setExitTransition(fade);
}
3、使用finishAfterTransition()
函数可以在退出Activity时也有过渡动画
TryTextView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finishAfterTransition();
finish();
}
});
4、最后启动使用过渡的Activity
startActivity(intent,
ActivityOptions.makeSceneTransitionAnimation(this).toBundle());
3、使用共享元素过渡动画
我们先来看一下一个共享元素过渡动画的实例:
可以看到这个蓝色的图以及它的标题就是两个Activity之间的共享元素,同样Android为共享元素之间的过渡准备了四个类:
1、changeBounds - 为目标视图布局边界的变化添加动画效果。
2、changeClipBounds - 为目标视图裁剪边界的变化添加动画效果。
3、changeTransform - 为目标视图缩放和旋转方面的变化添加动画效果。
4、changeImageTransform - 为目标图片尺寸和缩放方面的变化添加动画效果。
那么我们要实现这两个共享元素之间的过渡可以按照以下步骤:
1、在style里将是否使用activity过渡的标志位设为true,或者使用相应处理代码
<style name="BaseAppTheme" parent="Theme.AppCompat.Light">
<item name="android:windowContentTransitions">true</item>
</style>
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState)
getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS)
}
2、在样式中指定共享元素过渡
<style name="AppTheme" parent="Theme.AppCompat.Light">
<!-- Set the transitions which are used for the entrance and exit of shared elements -->
<item name="android:windowSharedElementEnterTransition" tools:ignore="NewApi">
@transition/grid_detail_transition
</item>
<item name="android:windowSharedElementExitTransition" tools:ignore="NewApi">
@transition/grid_detail_transition
</item>
</style>
3、将过渡定义成xml资源
在transition文件夹里的grid_detail_transition.xml文件里
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
<!-- changeBounds is used for the TextViews which are shared -->
<changeBounds />
<!-- changeImageTransform is used for the ImageViews which are shared -->
<changeImageTransform />
</transitionSet>
4、将共享元素设置统一的TransitionName
如果只有一个共享元素,设置统一的TransitionName就可以了,由于这里在启动Activity时有多个共享元素,所以这里定义两个布局中的共享元素,并创建一个 ActivityOptions 对象
DetailActivity.java
里定义TransitionName
ViewCompat.setTransitionName(mHeaderImageView, VIEW_NAME_HEADER_IMAGE);
ViewCompat.setTransitionName(mHeaderTitle, VIEW_NAME_HEADER_TITLE);
其中
public static final String VIEW_NAME_HEADER_IMAGE = "detail:header:image";
public static final String VIEW_NAME_HEADER_TITLE = "detail:header:title";
5、启动过渡的Activity
(1) 使用makeSceneTransitionAnimation()
函数,第一个参数是origin view,第二个参数是设置的TransitionName
MainActivity.java
里创建一个 ActivityOptions 对象
ActivityOptionsCompat activityOptions = ActivityOptionsCompat.makeSceneTransitionAnimation(
MainActivity.this,
// Now we provide a list of Pair items which contain the view we can transitioning
// from, and the name of the view it is transitioning to, in the launched activity
new Pair<>(view.findViewById(R.id.imageview_item),
DetailActivity.VIEW_NAME_HEADER_IMAGE),
new Pair<>(view.findViewById(R.id.textview_name),
DetailActivity.VIEW_NAME_HEADER_TITLE));
(2)在DetailActivity.java
中使用一个loadItem()
函数用来展示图片的放大缩小
private void loadItem() {
mHeaderTitle.setText(getString(R.string.image_header, mItem.getName(), mItem.getAuthor()));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && addTransitionListener()) {
loadThumbnail();//小图片
} else {
loadFullSizeImage();//大图片
}
}
Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP
这个判断是用来检查系统的版本的,其中还使用了一个监听函数addTransitionListener()
private boolean addTransitionListener() {
final Transition transition = getWindow().getSharedElementEnterTransition();
if (transition != null) {
// There is an entering shared element transition so add a listener to it
transition.addListener(new Transition.TransitionListener() {
@Override
public void onTransitionEnd(Transition transition) {
// As the transition has ended, we can now load the full-size image
loadFullSizeImage();
// Make sure we remove ourselves as a listener
transition.removeListener(this);
}
...
}
(3)最后启动过渡
ActivityCompat.startActivity(MainActivity.this, intent, activityOptions.toBundle());
注意!如需在完成第二个 Activity 时反转场景过渡动画,要调用 Activity.finishAfterTransition()
函数,而不是 Activity.finish()
函数
至此就能实现开头那样的共享元素过渡了!
如需要源码下载可参考Android官方链接共享元素过渡动画
作者:刘俊豪
原文链接:点击这里