如何在Jetpack Compose中使用自定义Composable作为启动页?
问题背景
已编写Logo.kt作为自定义启动页Composable组件,当前项目使用SplashScreen API配置启动页,希望替换默认图标为该Logo组件,同时避免延迟跳转导致的白屏问题,且项目基于Navigation Compose实现页面导航。
解决方案步骤
1. 调整SplashScreen主题配置
修改themes.xml,移除默认图标配置,将主题背景设置为Logo渐变的起始色,避免切换时的视觉断层:
<style name="Theme.CustomSplashScreenTheme" parent="Theme.SplashScreen"> <!-- 与Logo渐变起始色保持一致,避免切换突兀 --> <item name="windowSplashScreenBackground">@color/splash_start_color</item> <item name="windowSplashScreenAnimationDuration">600</item> <item name="postSplashScreenTheme">@style/Theme.BaeCallingApp</item> <!-- 移除默认图标配置,使用自定义Composable替代 --> </style>
同时在colors.xml中添加对应颜色:
<color name="splash_start_color">#0A1478</color>
2. 优化Logo组件的字体加载逻辑
避免Composable重组时重复加载字体,使用remember缓存字体资源:
@Composable fun Logo(modifier: Modifier = Modifier) { val gradient = Brush.verticalGradient( colors = listOf( Color(0xFF0A1478), Color(0xFFBEC8FF) ) ) val context = LocalContext.current // 用remember缓存字体,提升性能 val customTypeFace = remember { context.resources.getFont(R.font.marckscript_regular) } Canvas( modifier = modifier .fillMaxSize() .background(gradient) ) { val padding = 20 val path = Path().apply { moveTo(x = padding.toFloat() * 6, y = center.y) lineTo(x = size.width - padding * 6, y = center.y) } this.drawContext.canvas.nativeCanvas.apply { drawTextOnPath( "BAE Calling App", path.asAndroidPath(), 0f, 0f, Paint().apply { this.color = android.graphics.Color.WHITE this.textSize = 120f this.textAlign = Paint.Align.CENTER this.typeface = customTypeFace } ) } } } @Preview(showBackground = true) @Composable fun LogoPreview() { BaeCallingAppTheme { Logo() } }
3. 修改MainActivity逻辑,绑定SplashScreen与Logo组件
利用SplashScreen API的setContent方法直接加载自定义Composable,同时通过ViewModel状态控制启动页显示时长:
class MainActivity : ComponentActivity() { @Inject lateinit var splashViewModel: SplashViewModel override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) installSplashScreen().apply { // 将Logo组件设置为SplashScreen的内容 setContent { BaeCallingAppTheme { Logo() } } // 加载过程中保持启动页,完成后自动切换 setKeepOnScreenCondition { splashViewModel.isLoading.value } } // SplashScreen消失后加载导航页面 setContent { BaeCallingAppTheme { val screen by splashViewModel.startDestination.collectAsStateWithLifecycle() setUpNavController( controller = rememberNavController(), startDestination = screen ) } } } }
核心说明
- 使用SplashScreen API的
setContent方法是官方支持的自定义启动页方式,可在系统启动页窗口直接展示Composable内容,避免白屏问题; - 通过ViewModel的
isLoading状态控制启动页显示时长,无需手动延迟跳转; - 缓存字体资源符合Composable最佳实践,避免重复加载导致的性能损耗。
内容的提问来源于stack exchange,提问作者Harry
相关产品推荐
相关产品推荐

