如何避免覆盖Compose函数默认参数?Kotlin调用场景疑问
Kotlin Compose 动态控制是否覆盖默认参数的解决方案
问题场景
原Card组件代码:
@Composable @NonRestartableComposable fun Card( modifier: Modifier = Modifier, shape: Shape = MaterialTheme.shapes.medium, backgroundColor: Color = MaterialTheme.colors.surface, contentColor: Color = contentColorFor(backgroundColor), border: BorderStroke? = null, elevation: Dp = 1.dp, content: @Composable () -> Unit ) { Surface( modifier = modifier, shape = shape, color = backgroundColor, contentColor = contentColor, elevation = elevation, border = border, content = content ) }
调用代码示例:
@Composable private fun Item(item: itemEntity, onClick: () -> Unit) { val backgroundColor = if (item.readAt.isEmpty()) { MaterialTheme.colors.primary.copy(alpha = 0.1f) } else { // 不做处理? } Card( backgroundColor = backgroundColor, ) { // 内容区域 } }
疑问:Kotlin是否不允许调用带默认参数的函数时,动态选择是否覆盖默认值?如果不想写多个if分支调用Card,也不想硬写默认值(避免后续默认值变更时同步修改),该如何解决?
解决方案
1. 封装扩展函数支持null占位符
自己封装一个Card扩展函数,允许backgroundColor传null,当为null时自动使用原组件的默认值:
@Composable fun Card( modifier: Modifier = Modifier, shape: Shape = MaterialTheme.shapes.medium, backgroundColor: Color? = null, contentColor: Color = contentColorFor(backgroundColor ?: MaterialTheme.colors.surface), border: BorderStroke? = null, elevation: Dp = 1.dp, content: @Composable () -> Unit ) { androidx.compose.material.Card( modifier = modifier, shape = shape, backgroundColor = backgroundColor ?: MaterialTheme.colors.surface, contentColor = contentColor, border = border, elevation = elevation, content = content ) }
调用时,不需要自定义背景色就传null:
@Composable private fun Item(item: itemEntity, onClick: () -> Unit) { val backgroundColor = if (item.readAt.isEmpty()) { MaterialTheme.colors.primary.copy(alpha = 0.1f) } else { null } Card(backgroundColor = backgroundColor) { // 内容区域 } }
这种方式最灵活,后续原Card的默认值变更时,封装的函数会自动同步,无需修改调用代码。
2. 用公共内容变量简化分支调用
如果不想封装函数,可将Card内部的公共内容抽成单独的Composable变量,避免分支里重复编写内容代码:
@Composable private fun Item(item: itemEntity, onClick: () -> Unit) { val cardContent = @Composable { // 这里写Card内部的所有公共内容 } if (item.readAt.isEmpty()) { Card(backgroundColor = MaterialTheme.colors.primary.copy(alpha = 0.1f), content = cardContent) } else { Card(content = cardContent) } }
3. 直接复用原默认值表达式
如果只是临时场景,也可以直接在else分支使用原Card的默认值表达式:
@Composable private fun Item(item: itemEntity, onClick: () -> Unit) { val backgroundColor = if (item.readAt.isEmpty()) { MaterialTheme.colors.primary.copy(alpha = 0.1f) } else { MaterialTheme.colors.surface } Card(backgroundColor = backgroundColor) { // 内容区域 } }
注意:如果后续原Card的backgroundColor默认值修改,这里需要手动同步更新,灵活性较差。
内容的提问来源于stack exchange,提问作者David
相关产品推荐
相关产品推荐

