我目前正在将 XML 布局迁移到 Jetpack Compose。
我开发了一个通用的
androidx.compose.material3.DropdownMenu
Compose 函数,我希望在我当前的 Android 项目中的任何地方使用它,并通过单击 XML Button
显示(展开)它。
这是我当前的代码,它确实可以按预期工作。但是我不确定这是否是最好/正确的方法。
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContentView(R.layout.activity_second)
val button = findViewById<Button>(R.id.showDropDown)
val showDropDownMenu = mutableStateOf(true)
button.setOnClickListener {
showDropDownMenu.value = true
}
findViewById<ComposeView>(R.id.composeDropDownMenuOuter).apply {
setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
setContent {
DropDownMenuUi(showDropDownMenu)
}
}
}
DropDownMenuUi
可组合项类似于:
@Composable
fun DropDownMenuUi(showDropDownMenu: MutableState<Boolean>) {
val expanded by remember { mutableStateOf(showDropDownMenu) }
DropdownMenu(
modifier = ddm.modifier ?: Modifier.padding(start = 10.dp, end = 10.dp),
expanded = expanded.value,
onDismissRequest = { expanded.value = false },
offset = ddm.offset ?: DpOffset(0.dp, 0.dp)
) {
...
...
...
...
}
...
...
...
我主要关心的是使用
val showDropDownMenu = mutableStateOf(true)
,这对于撰写来说可以吗?
我可以采用更“组合”的方法吗?
虽然代码有效,但从 Activity 中的
mutableStateOf()
在可组合项中创建 mutableStateOf()
是多余的。另外,不建议直接从嵌套可组合项覆盖 MutableState
。相反,您的可组合项应该有一个回调。
另一个最近的转变是,当我们不在可组合范围内时,我们应该更喜欢
MutableStateFlow
(来自Kotlin库)而不是mutableStateOf
(来自Compose库)。通过这样做,我们将 ViewModel 或 Activity 代码与可组合库解耦。然后,您可以使用 MutableStateFlow
在您的可组合项中收集
collectAsStateWithLifecycle()
。
请尝试重构您的
DropDownMenuUi
可组合项,如下所示:
@Composable
fun DropDownMenuUi(showDropDownMenu: Boolean, onDismiss: () -> Unit) {
DropdownMenu(
//...
expanded = showDropDownMenu,
onDismissRequest = onDismiss,
// ...
) {
//...
}
}
然后,在您的
onCreate
函数中,声明一个 MutableStateFlow
,如下所示:
val showDropDownMenuState = MutableStateFlow(true)
button.setOnClickListener {
showDropDownMenuState.value = true
}
最后,按如下方式调用您的可组合项:
setContent {
// use below variable for reading the showDropDownMenuState
val showDropDownMenu by showDropDownMenuState.collectAsStateWithLifecycle()
DropDownMenuUi(
showDropDownMenu = showDropDownMenu,
onDismiss = {
showDropDownMenuState.value = false
}
)
}