如何正确配置Android应用同时使用Navigation Component与Splash Screen API并解决setContent问题
问题根因
SplashScreen.installSplashScreen()是Activity层级的API,必须在Activity的onCreate生命周期、super.onCreate调用前执行,不能放在Fragment的生命周期中调用setContentView()是Activity专属方法,在Fragment的onCreateView中调用会触发布局层级异常- 单独创建Splash Screen专属Fragment属于冗余实现,新版Splash Screen API会直接接管系统启动过渡流程,无需额外编写启动页页面
完整配置步骤
1. 引入依赖(Module级build.gradle)
dependencies { // Splash Screen API implementation "androidx.core:core-splashscreen:1.0.1" // Navigation Component相关依赖 implementation "androidx.navigation:navigation-fragment:2.5.3" implementation "androidx.navigation:navigation-ui:2.5.3" }
2. 配置启动主题
在res/values/themes.xml中新增Splash Screen专属启动主题:
<style name="Theme.App.Splash" parent="Theme.SplashScreen"> <!-- 启动页背景色 --> <item name="windowSplashScreenBackground">@color/white</item> <!-- 启动页中心图标,支持动画 --> <item name="windowSplashScreenAnimatedIcon">@mipmap/ic_launcher_round</item> <!-- 动画时长,最大1000ms --> <item name="windowSplashScreenAnimationDuration">1000</item> <!-- 启动页结束后切换的App正常主题 --> <item name="postSplashScreenTheme">@style/Theme.YourAppNormal</item> </style>
在AndroidManifest.xml中给主Activity绑定启动主题:
<activity android:name=".MainActivity" android:exported="true" android:theme="@style/Theme.App.Splash"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>
3. Activity层初始化Splash Screen与Navigation
主ActivityonCreate逻辑如下,不要在Fragment中做相关操作:
@Override protected void onCreate(Bundle savedInstanceState) { // 必须在super.onCreate和setContentView之前调用 SplashScreen splashScreen = SplashScreen.installSplashScreen(this); super.onCreate(savedInstanceState); // 设置导航宿主布局 setContentView(R.layout.activity_main); // 可选:如果需要等待初始化任务完成再退出启动页,添加该逻辑 splashScreen.setKeepOnScreenCondition(() -> { // 返回true保持启动页,返回false关闭启动页进入应用 return !globalInitTaskFinished; }); // 初始化Navigation Component NavHostFragment navHostFragment = (NavHostFragment) getSupportFragmentManager() .findFragmentById(R.id.nav_host_fragment); NavController navController = navHostFragment.getNavController(); NavigationUI.setupActionBarWithNavController(this, navController); }
activity_main.xml布局示例:
<?xml version="1.0" encoding="utf-8"?> <androidx.fragment.app.FragmentContainerView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/nav_host_fragment" android:layout_width="match_parent" android:layout_height="match_parent" android:name="androidx.navigation.fragment.NavHostFragment" app:navGraph="@navigation/nav_graph" app:defaultNavHost="true" />
4. 导航图配置
直接将应用首页作为导航起始目的地即可,无需添加启动页Fragment节点:
<navigation xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/nav_graph" app:startDestination="@id/homeFragment"> <fragment android:id="@+id/homeFragment" android:name="com.yourpackage.HomeFragment" android:label="首页" /> <!-- 其他业务页面配置 --> </navigation>
原有代码修改建议
- 移除
SplashScreenFragment的所有相关逻辑,不需要单独维护启动页Fragment - 删除Fragment中的
SplashScreen.installSplashScreen与setContentView调用,相关逻辑统一放到主Activity的onCreate中执行
内容的提问来源于stack exchange,提问作者Edgard Oliveira
相关产品推荐
相关产品推荐

