本文基于Android 13
通过xml引入动画
适用于应用内有多个Activity的场景,这些Activity都在同一个Task任务栈内, 换而言之,下面的配置对Task之间的切换动画不生效,launchMode也会有影响,详细说明请参考 不同Android版本之间的区别
定义动画文件
在res/anim下定义两个动画文件
slide_in_left.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="@android:integer/config_mediumAnimTime"
android:fromXDelta="-100%"
android:toXDelta="0%"/>
</set>
slide_out_right.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="@android:integer/config_mediumAnimTime"
android:fromXDelta="0%"
android:toXDelta="100%"/>
</set>在style中指定动画
然后定义animation-themes.xml,引用上边定义的动画资源,定义style name = windowAnimationStyle,这个style中的动画字段也可以直接写入themes.xml中,省略一个文件, parent指定为:android:Animation.Activity
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Window animation style -->
<style name="windowAnimationStyle" parent="android:Animation.Activity">
<item name="android:activityOpenEnterAnimation">@anim/slide_in_left</item>
<item name="android:activityOpenExitAnimation">@anim/slide_out_right</item>
</style>
</resources>配置主题
在values/themes.xml主题中引用动画, parent指定为Theme.AppCompat或其子类, 引用动画关键属性: <item name="android:windowAnimationStyle">@style/windowAnimationStyle</item>
<resources xmlns:tools="http://schemas.android.com/tools">
<style name="Theme.Demo.WindowAnimation" parent="@style/Theme.AppCompat" >
<item name="android:windowEnableSplitTouch">false</item>
<item name="android:splitMotionEvents">false</item>
// 窗口动画
<item name="android:windowAnimationStyle">@style/windowAnimationStyle</item>
<item name="android:windowBackground">@color/transparent</item>
</style>
<style name="Theme.Demo.NoAnimation" parent="@style/Theme.AppCompat" >
<item name="android:windowEnableSplitTouch">false</item>
<item name="android:splitMotionEvents">false</item>
<item name="android:windowAnimationStyle">@null</item>
<item name="android:windowBackground">@color/transparent</item>
</style>
</resources>应用主题
最后在AndroidManifext.xml引入主题
应用到application
在application中添加 android:theme="@style/Theme.Demo"
<application
...
android:theme="@style/Theme.Demo.WindowAnimation"
<activity
android:name=".MainActivity"
...启动app后,在内部跳转activity,可以看到自定义的窗口过度动画
应用到指定Activity
<application
...
android:theme="@style/Theme.Demo.NoAnimation"
...
<activity
android:name=".CustomAnimationActivity"
android:theme="@style/Theme.Demo.WindowAnimation"
...
不同Android版本之间的区别
上边的动画属性还包括任务栈之间的切换动画
<item name="android:activityOpenEnterAnimation">@anim/slide_in_from_bottom</item>
<item name="android:activityCloseExitAnimation">@anim/slide_out_from_bottom</item>
<item name="android:taskOpenEnterAnimation">@anim/slide_in_from_bottom</item>
<item name="android:taskOpenExitAnimation">@anim/slide_out_from_bottom</item>
<item name="android:taskCloseExitAnimation">@anim/slide_out_from_bottom</item>
<item name="android:taskCloseEnterAnimation">@anim/slide_in_from_bottom</item>
<item name="android:taskToFrontEnterAnimation">@anim/slide_in_from_bottom</item>
<item name="android:taskToFrontExitAnimation">@anim/slide_out_from_bottom</item>
<item name="android:taskToBackExitAnimation">@anim/slide_out_from_bottom</item>
<item name="android:taskToBackEnterAnimation">@anim/slide_in_from_bottom</item>任务栈切换动画 taskOpenEnterAnimation 在Android R及以上版本失效,在Android Q上 通过back事件进后台后切换到前台失效,通过home事件进后台再切到前台有效,这里的切换到前台指的是通过adb shell am start -a 的方式,如果是通过点击launcher图标来启动的话,只有在Android O上有效
通过代码添加动画
动态设置主题
代码应用到Activity
在super.onCreate之前添加一行 setTheme(R.style.Theme_windowAnimation)
override fun onCreate(savedInstanceState: Bundle?) {
setTheme(R.style.Theme_windowAnimation)
super.onCreate()
...
}在Activity内部设置过度动画
同样,首先在res/anim/下配置好in和out的动画资源,在activity中,setContentView之前调用 overridePendingTransition 指定当前activity的动画资源
override fun onCreate(savedInstanceState: Bundle?) {
overridePendingTransition(R.anim.slide_in_from_bottom,R.anim.slide_out_from_bottom)
super.onCreate(savedInstanceState)
}在Android aosp模拟器测试过
从Android S开始 ,此函数只能为Task任务栈里边的activity添加过度动画,Task任务栈之间的动画切换只能使用系统默认动画,函数定义:
/**
* Call immediately after one of the flavors of {@link #startActivity(Intent)}
* or {@link #finish} to specify an explicit transition animation to
* perform next.
*
* <p>As of {@link android.os.Build.VERSION_CODES#JELLY_BEAN} an alternative
* to using this with starting activities is to supply the desired animation
* information through a {@link ActivityOptions} bundle to
* {@link #startActivity(Intent, Bundle)} or a related function. This allows
* you to specify a custom animation even when starting an activity from
* outside the context of the current top activity.
*
* <p>Af of {@link android.os.Build.VERSION_CODES#S} application can only specify
* a transition animation when the transition happens within the same task. System
* default animation is used for cross-task transition animations.
*
* @param enterAnim A resource ID of the animation resource to use for
* the incoming activity. Use 0 for no animation.
* @param exitAnim A resource ID of the animation resource to use for
* the outgoing activity. Use 0 for no animation.
*/
public void overridePendingTransition(int enterAnim, int exitAnim) {
overridePendingTransition(enterAnim, exitAnim, 0);
}对于Android 14
新增了一个接口overrideType 可选 OVERRIDE_TRANSITION_OPEN,OVERRIDE_TRANSITION_CLOSE
public void overrideActivityTransition(int overrideType, int enterAnim, int exitAnim, int backgroundColor) {
}启动Activity时设置动画
startActivity之后可以紧跟一个
overridePendingTransition来设置动画startActivity传入ActivityOptions参数
val activityOptions = ActivityOptions.makeCustomAnimation(context, R.anim.slide_in, 0 )
context.startActivity(intent, activityOptions.toBundle())一些动画不生效的场景
主题引用错误,引用主题的时候直接引用
R.style.windowAnimationStyle,应该引用R.style.Theme.Demo,WindowAnimationAndroid 版本限制,比如overridePendingTransition 在Android < S,对Task切换动画生效,高版本只对同一个Task内的Activity生效
受到启动模式影响,singleInstance模式下动画不会生效,因为每个Activity都位于不同的Task
在高版本中Android 已经不支持应用定义Task之间切换的动画