Jetpack Compose中如何使用依赖主题的字符串与drawable资源
有对应的实现方案,核心通过CompositionLocal挂载自定义主题资源实现,和XML里通过主题属性调用资源的逻辑完全对齐,实现方式如下:
具体实现步骤
1. 定义主题资源契约
和XML中提前定义自定义属性的逻辑一致,先定义数据类统一存放所有需要随主题切换的资源:
data class AppThemeResources( val homePageTitle: String, val placeholderDrawable: Drawable, // 其他需要绑定主题的资源都可以在此处扩展 )
接下来准备不同主题对应的资源实例,比如浅色/深色两套:
// 浅色主题资源 @Composable private fun getLightThemeResources() = AppThemeResources( homePageTitle = stringResource(R.string.home_title_light), placeholderDrawable = ContextCompat.getDrawable(LocalContext.current, R.drawable.ic_placeholder_light)!! ) // 深色主题资源 @Composable private fun getDarkThemeResources() = AppThemeResources( homePageTitle = stringResource(R.string.home_title_dark), placeholderDrawable = ContextCompat.getDrawable(LocalContext.current, R.drawable.ic_placeholder_dark)!! )
2. 全局挂载主题资源
我们通过CompositionLocal把资源传递到整个Compose树,作用等价于XML中全局可用的?attr/xxx主题属性:
// 定义全局可访问的CompositionLocal val LocalAppThemeResources = staticCompositionLocalOf<AppThemeResources> { error("未找到AppThemeResources,请确保父节点已配置自定义主题") }
然后在你项目的自定义主题中,根据当前主题状态传入对应的资源实例:
@Composable fun MyCustomAppTheme( isDarkMode: Boolean = isSystemInDarkTheme(), content: @Composable () -> Unit ) { val themeColors = if (isDarkMode) DarkColorPalette else LightColorPalette val themeResources = if (isDarkMode) getDarkThemeResources() else getLightThemeResources() MaterialTheme( colors = themeColors, typography = AppTypography, shapes = AppShapes ) { // 把自定义资源注入Compose树,所有子节点都可以访问 CompositionLocalProvider( LocalAppThemeResources provides themeResources, content = content ) } }
3. 业务侧调用
之后在任意Composable中都可以直接读取当前主题对应的资源,切换主题时会自动刷新,和XML中调用主题属性的效果完全一致:
@Composable fun HomePage() { val themeRes = LocalAppThemeResources.current Column(modifier = Modifier.fillMaxSize()) { // 调用主题绑定的字符串 Text(text = themeRes.homePageTitle, style = MaterialTheme.typography.h1) // 调用主题绑定的Drawable Image( painter = rememberDrawablePainter(drawable = themeRes.placeholderDrawable), contentDescription = "占位图" ) } }
扩展说明
- 如果你的字符串需要适配多语言,直接在资源实例化时用
stringResource读取对应的strings.xml资源即可,切换系统语言时会自动更新 - 如果仅需要局部覆盖资源配置,不需要全局切换主题,也可以在局部单独调用
CompositionLocalProvider覆盖上层的资源配置,灵活性远高于XML的主题配置
内容的提问来源于stack exchange,提问作者Android Newcomer
相关产品推荐
相关产品推荐

