如何在Android 12 Splashscreen API中实现共享元素转场?
实现SplashScreen图标到主Activity的共享元素转场
可以实现,而且从Android 12(API 31)开始,系统自带的SplashScreen API就能直接支持这种转场,无需依赖Fragment或额外Activity。下面是针对Kotlin新手的分步实现方案:
1. 配置SplashScreen主题
在res/values/styles.xml(或针对高版本的res/values-v31/styles.xml)中定义SplashScreen专属主题,指定图标、背景色和转场参数:
<style name="Theme.App.SplashScreen" parent="Theme.SplashScreen"> <!-- 设置启动页图标 --> <item name="windowSplashScreenAnimatedIcon">@drawable/ic_app_icon</item> <!-- 设置图标背景色 --> <item name="windowSplashScreenBackgroundColor">@color/white</item> <!-- 设置转场时长,需与主Activity转场时长匹配 --> <item name="windowSplashScreenAnimationDuration">500</item> <!-- 指定启动完成后切换到的主Activity主题 --> <item name="postSplashScreenTheme">@style/Theme.App.Main</item> </style>
接着在AndroidManifest.xml中给主Activity绑定这个启动主题:
<activity android:name=".MainActivity" android:theme="@style/Theme.App.SplashScreen" android:exported="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>
2. 在MainActivity中处理转场逻辑
在MainActivity的onCreate方法中,先初始化SplashScreen,再通过回调获取图标View并配置共享元素转场:
import android.os.Bundle import android.view.View import androidx.appcompat.app.AppCompatActivity import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen import androidx.core.view.ViewCompat import androidx.transition.TransitionInflater class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { // 必须在super.onCreate之前初始化SplashScreen val splashScreen = installSplashScreen() super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // 给主Activity中作为共享目标的View设置唯一transitionName val targetIcon = findViewById<View>(R.id.main_app_icon) ViewCompat.setTransitionName(targetIcon, "app_icon_transition") // 监听SplashScreen退出动画 splashScreen.setOnExitAnimationListener { splashScreenView -> // 获取SplashScreen中的图标View val splashIcon = splashScreenView.iconView // 设置与目标View一致的transitionName ViewCompat.setTransitionName(splashIcon, "app_icon_transition") // 加载自定义共享元素转场动画 val transition = TransitionInflater.from(this) .inflateTransition(R.transition.shared_element_transition) // 动画结束后移除SplashScreen视图 transition.addListener(object : androidx.transition.TransitionListener { override fun onTransitionStart(transition: androidx.transition.Transition) {} override fun onTransitionCancel(transition: androidx.transition.Transition) { splashScreenView.remove() } override fun onTransitionEnd(transition: androidx.transition.Transition) { splashScreenView.remove() } override fun onTransitionPause(transition: androidx.transition.Transition) {} override fun onTransitionResume(transition: androidx.transition.Transition) {} }) // 启动转场动画 androidx.transition.TransitionManager.beginDelayedTransition( splashScreenView, transition ) // 修改图标状态配合动画(比如缩小+淡出) splashIcon.scaleX = 0.5f splashIcon.scaleY = 0.5f splashIcon.alpha = 0f } } }
3. 创建共享元素转场动画文件
在res/transition目录下新建shared_element_transition.xml(没有transition目录则手动创建),定义转场动画逻辑:
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android"> <!-- 共享元素的位置、大小变化动画 --> <changeBounds /> <changeTransform /> <!-- 目标图标的淡入动画 --> <fade> <targets> <target android:targetId="@id/main_app_icon" /> </targets> </fade> </transitionSet>
4. 配置主Activity布局的目标View
在activity_main.xml中添加一个作为共享元素目标的View(比如ImageView):
<ImageView android:id="@+id/main_app_icon" android:layout_width="64dp" android:layout_height="64dp" android:src="@drawable/ic_app_icon" <!-- 根据需求添加布局对齐属性,比如居中 --> />
注意事项
- 若需兼容API 21及以上版本,需引入AndroidX的SplashScreen库:
androidx.core:core-splashscreen:1.0.1+ - 两个View的
transitionName必须完全一致,否则转场不会生效 - 转场时长需保持统一,避免动画衔接脱节
内容的提问来源于stack exchange,提问作者Tenka428
相关产品推荐
相关产品推荐

