文本中主要是总结activity切换动画相关的知识点,切换动画指的是是activity跳转时的动画效果,共有三种方式实现activity切换时实现动画效果,这里将一一介绍。
调用startActivity或者finish方法实现activity切换的时候,都涉及到两个activity的动画 ,旧的Activity的退出动画和新的Activity的显示动画;所以我们的activity跳转动画是分为两个部分的:一个Activity的销毁动画与一个Activity的显示动画。
一、使用style的方式定义Activity的切换动画
<style name="WindowAnimation">
<item name="android:activityOpenEnterAnimation">@anim/open</item>
<item name="android:activityOpenExitAnimation">@anim/close</item>
<item name="android:activityCloseEnterAnimation">@anim/open</item>
<item name="android:activityCloseExitAnimation">@anim/close</item>
</style>
而在windowAnimationStyle中存在四种动画:
activityOpenEnterAnimation : a启动b时,b进入的动画
activityOpenExitAnimation : a启动b时,a消失的动画
activityCloseEnterAnimation : 从b退出时,a进入的动画
activityCloseExitAnimation : 从b退出时,b消失的动画
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="android:windowAnimationStyle">@style/WindowAnimation</item>
</style>
- 为application或者activity设置theme
其中这里的windowAnimationStyle就是我们定义Activity切换动画的style。而WindowAnimation中定义的就是动画文件。
也就是说通过为Appliation设置style,然后为windowAnimationStyle设置动画文件就可以全局的为Activity的跳转配置动画效果。
也可以单独对某个activity通过设置theme主题设置动画。
二、使用overridePendingTransition方法实现Activity跳转动画 (android 2.0开始)
void overridePendingTransition (int enterAnim, int exitAnim)
Call immediately after one of the flavors of startActivity(Intent) or finish() to specify an explicit transition animation to perform next.
Parameters
enterAnim int: A resource ID of the animation resource to use for the incoming activity. Use 0 for no animation.
exitAnim int: A resource ID of the animation resource to use for the outgoing activity. Use 0 for no animation.
这段注释,我们能够知道:
overridePendingTransition方法需要在startAtivity方法或者是finish方法调用之后立即执行
参数enterAnim表示的是从Activity a跳转到Activity b,进入b时的动画效果
参数exitAnim表示的是从Activity a跳转到Activity b,离开a时的动过效果
若进入b或者是离开a时不需要动画效果,则可以传值为0
例如:
startActivity(new Intent(context,SecondActivity.class))
overridePendingTransition(R.anim.right_in,R.anim.right_out)
注:延迟执行没有动画效果,但是可以在子线程中执行
三、ActivityOptions方式实现 (android 5.0开始)
1、 java代码方式设置动画
- 在跳转的Activity中设置contentFeature
getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
Transition explode =
TransitionInflater.from(this).inflateTransition(R.transition.explode);
其中R.transition.explode就是要执行的动画,是在res/transition目录下的xml文件,我们使用的是系统内置的Explode效果动画,也可以自己定义动画效果。 在setContentView()之后调用就可以。
上面是创建好的切换动画,接下来就是要告诉当前窗口,在什么情况下去使用动画效果啦,你可以根据你的需求在不同的切换情景中选择不同的效果:
getWindow().setExitTransition(explode);
getWindow().setEnterTransition(explode);
getWindow().setReenterTransition(explode);
跟我们之前使用的startActivity(Intent intent);不同,这里多了一个参数Bundle,我们是先通过makeSceneTransitionAnimation函数创建一个ActivityOptions对象,再将其转为Bundle对象:
startActivity(intent,ActivityOptions.makeSceneTransitionAnimation(this).toBundle());
2、style方式设置动画
可以直接在application的theme主题中,设置transition动画的方式实现,这种设置还是全局的。在设置完之后,只需上述最后一步调用startActivity(intent,bundle)就可以了。
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="android:windowExitTransition">@transition/slide_h</item>
<item name="android:windowEnterTransition">@transition/slide_h</item>
<item name="android:windowReenterTransition">@transition/slide_h</item>
</style>
3、定义动画效果
Explode即爆炸效果,使用Explode效果很简单,在res/transition目录下新建一个xml文件(如explode.xml),内容如下:其中duration表示Explode动画持续时间,由于是Activity之间的切换,最好不要把动画时间设置过大,一般取200~500毫秒比较合适。
<explode xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="300" />
即滑动效果,使用Slide跟Explode类似,都是在res/transition目录下新建一个xml文件(如slide.xml),内容如下:其中,slideEdge表示起始滑动的侧边位置,end表示右侧,start表示左侧,top表示顶部,bottom表示底侧,各种效果你可以亲自试试。
<slide xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:interpolator/decelerate_cubic"
android:slideEdge="end"/>
如果你不希望顶部的状态栏以及底部的导航栏一起执行动画,可以在xml中指定:
<slide xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:interpolator/decelerate_cubic"
android:slideEdge="end">
<targets>
<target android:excludeId="@android:id/navigationBarBackground" />
<target android:excludeId="@android:id/statusBarBackground" />
</targets>
</slide>
Fade效果即淡化效果,使用淡化效果依然是很简单,在res/transition目录下新建一个xml文件(如fade.xml),内容如下:Fade效果就是将View逐步淡化。
<fade xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="300" />
4、动画共享组件的方式实现
即共享元素效果,与前面几种效果不同的是,共享元素效果是将前面一个Activity的某个子View与后面一个Activity的某个子View之间有过渡效果,接下来我们看看如何实现这个效果:
- 将两个Activity中需要过渡的View加上Android:transitionName属性
两个View的android:transitionName属性取值要一致。
第一个Activity布局中:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<View
android:id="@+id/firstSharedView"
android:layout_width="100dp"
android:layout_height="100dp"
android:background="#00cc00"
android:onClick="onClick"
android:transitionName="sharedView" />
</RelativeLayout>
第二个Activity布局:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<View
android:layout_width="match_parent"
android:layout_height="300dp"
android:layout_alignParentBottom="true"
android:background="#00cc00"
android:onClick="onClick"
android:transitionName="sharedView" />
</RelativeLayout>
两个绿色的View都添加android:transitionName属性,并且取名一致。
ActivityOptions的makeSceneTransitionAnimation函数第一个参数Activity没啥解释的,第二个参数就是第一个Activity中的View对象,第三个参数就是两个Activity的View的 android:transitionName属性的值。
startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(this, firstSharedView, "sharedView").toBundle());
也可以同时让两个View有这样的效果:
除了需要将两个Activity中需要过渡的View对应取相同的名称外,还需将需要过渡的View和transitionName取值对应的String这两个对象封装到一个Pair对象中:
Pair first = new Pair<>(firstSharedView,
ViewCompat.getTransitionName(firstSharedView));
Pair second = new Pair<>(secondSharedView,
ViewCompat.getTransitionName(secondSharedView));
然后调用ActivityOptionsCompat类的makeSceneTransitionAnimation的另一个重载函数
makeSceneTransitionAnimation(Activity activity, Pair
ActivityOptionsCompat transitionActivityOptions =
ActivityOptionsCompat.makeSceneTransitionAnimation(this, first, second);
最后调用startActivity:
ActivityCompat.startActivity(this,intent, transitionActivityOptions.toBundle())
总结:
1、在使用上述前两种方法设置activity动画的时候发现一个问题:如果离开a时不需要动画,只设置了进入b的动画,此时会有短暂的黑屏才会出现进入b的动画。
解决方法有两种:
1) 设置相应的消失动画,如果不想设置消失动画,可以使用写一个假动画,这个动画是没有任何效果,只是为了避免出现黑屏,运行效果为原acticity静止不动,新启动的activity执行进入动画。
2) 对进入的activity b设置theme主题为透明
<style name="ActivityTheme" parent="AppTheme">
<item name="android:windowIsTranslucent">true</item>
</style>
注:此时会有一个问题,就是离开a的时候会不走onstop()方法,可能会造成问题。
2、动画执行优先级:
系统动画 < AppTheme < overridePendingTransition\ActivityOptionsCompat
可以根据第一种方式定义动画主题,并设置到application上,将整个应用的切换动画统一,如果某个页面有特殊要求,再根据不用需求使用第二或第三种类型单独处理。