Kotlin Jetpack Compose中能否将Drawable图片用作图标?
问题解答
1. 能否用drawable自定义图片作为图标?
完全可以。在Jetpack Compose中,你可以通过painterResource加载drawable里的自定义图片,配合Icon或Image组件显示:
// 导航栏、按钮等图标场景用Icon组件 Icon( painter = painterResource(id = R.drawable.your_custom_icon), contentDescription = "图标描述" // 用于无障碍访问 ) // 更灵活的图片展示用Image组件 Image( painter = painterResource(id = R.drawable.your_custom_icon), contentDescription = "图片描述", modifier = Modifier.size(24.dp) // 自定义大小 )
2. 解决"@Composable invocations can only happen from the context of a @Composable function."错误
这个错误的核心原因是你在非Composable环境里调用了Composable函数。从你的密封类写法来看,应该是直接在密封类对象中定义/调用了Icon这类Composable组件——而密封类的对象初始化属于普通代码上下文,不是Composable上下文,所以会报错。
正确的密封类写法:
密封类只存储路由、标题、图标资源ID等纯数据,不要包含Composable逻辑:
sealed class BottomBarScreen( val route: String, val title: String, val iconResId: Int // 只存图标资源ID ) { object Home : BottomBarScreen("home", "首页", R.drawable.ic_home) object Search : BottomBarScreen("search", "搜索", R.drawable.ic_search) object Profile : BottomBarScreen("profile", "我的", R.drawable.ic_profile) }
在Composable中使用密封类:
在带有@Composable注解的函数或lambda里,再通过密封类的iconResId加载并显示图标:
@Composable fun CustomBottomBar( currentRoute: String, onScreenChange: (String) -> Unit ) { BottomNavigation { listOf(BottomBarScreen.Home, BottomBarScreen.Search, BottomBarScreen.Profile).forEach { screen -> val isSelected = currentRoute == screen.route BottomNavigationItem( selected = isSelected, onClick = { onScreenChange(screen.route) }, icon = { // 这里是Composable上下文,可安全调用Icon组件 Icon( painter = painterResource(id = screen.iconResId), contentDescription = screen.title ) }, label = { Text(text = screen.title) } ) } } }
关键注意点:
- 所有Composable函数(比如
Icon、Text、BottomNavigationItem)必须在带有@Composable注解的函数、lambda或属性中调用 - 数据类/密封类这类纯数据结构,只负责存储数据,不要混入UI渲染逻辑
内容的提问来源于stack exchange,提问作者Devuixe
相关产品推荐
相关产品推荐

