Jetpack Compose:自定义组件中的嵌套权重
Jetpack Compose: Nested weight in custom component
假设我有一个按钮,在第一次点击时会展开以显示文本,并在第二次点击时执行操作——因此在执行操作之前充当一种确认。
@Compose
fun ExpandingConfirmButton(onConfirm: () -> Unit) {
// expanded state of the button
val (expanded, setExpanded) = remember { mutableStateOf(false) }
// animating weight. make the button larger when it is tapped once
val weight = animate(if (expanded) 10F else 2F)
Button(onClick = {
// only fire the action after two taps
if(expanded) {
onConfirm()
}
setExpanded(!expanded)
}) {
Icon(Icons.Dfault.Delete)
// only show the text if the button has already been clicked once,
// otherwise just show the icon
if(expanded) {
Text(text = "Delete", softWrap = false)
}
}
}
我会像这样使用那个按钮:
@Composable
fun PersonList(people: List<Person>) {
// some database service exposed via an ambient
val dataService = DataService.current
LazyColumnFor(items = people) {
Row() {
Text(text = it.firstName, modifier = Modifier.weight(10F))
// on the first tap, the button should take up half of the row
ExpandingConfirmButton(onConfirm = { dataService.deletePerson(it) })
}
}
}
这一切看起来都很简单。事实上,在我将 ExpandingConfirmButton
拆分成它自己的组件之前,将 Button()
直接包装在我的 PersonList
组件中之前,它工作得很好。
但是,似乎 Row
不太清楚当重量在其自己的组件内发生变化时如何处理按钮。按钮内的文本显示,但大小不变。这是否与 Row
的 RowScope
未被 ExpandingConfirmButton
内 Button
组件上的 Modifier
使用有关?如果是这样,我该如何使用它?
我最后做的基本上只是使用 .animateContentSize()
修饰符。
@Compose
fun ExpandingConfirmButton(onConfirm: () -> Unit) {
// expanded state of the button
val (expanded, setExpanded) = remember { mutableStateOf(false) }
Button(
modifier = Modifier.animateContentSize(), // do this
onClick = {
// only fire the action after two taps
if(expanded) {
onConfirm()
}
setExpanded(!expanded)
}) {
Icon(Icons.Default.Delete)
// only show the text if the button has already been clicked once,
// otherwise just show the icon
if(expanded) {
Text(text = "Delete", softWrap = false)
}
}
}
真的就是这么简单。不要乱用手动宽度、重量或类似的东西。
假设我有一个按钮,在第一次点击时会展开以显示文本,并在第二次点击时执行操作——因此在执行操作之前充当一种确认。
@Compose
fun ExpandingConfirmButton(onConfirm: () -> Unit) {
// expanded state of the button
val (expanded, setExpanded) = remember { mutableStateOf(false) }
// animating weight. make the button larger when it is tapped once
val weight = animate(if (expanded) 10F else 2F)
Button(onClick = {
// only fire the action after two taps
if(expanded) {
onConfirm()
}
setExpanded(!expanded)
}) {
Icon(Icons.Dfault.Delete)
// only show the text if the button has already been clicked once,
// otherwise just show the icon
if(expanded) {
Text(text = "Delete", softWrap = false)
}
}
}
我会像这样使用那个按钮:
@Composable
fun PersonList(people: List<Person>) {
// some database service exposed via an ambient
val dataService = DataService.current
LazyColumnFor(items = people) {
Row() {
Text(text = it.firstName, modifier = Modifier.weight(10F))
// on the first tap, the button should take up half of the row
ExpandingConfirmButton(onConfirm = { dataService.deletePerson(it) })
}
}
}
这一切看起来都很简单。事实上,在我将 ExpandingConfirmButton
拆分成它自己的组件之前,将 Button()
直接包装在我的 PersonList
组件中之前,它工作得很好。
但是,似乎 Row
不太清楚当重量在其自己的组件内发生变化时如何处理按钮。按钮内的文本显示,但大小不变。这是否与 Row
的 RowScope
未被 ExpandingConfirmButton
内 Button
组件上的 Modifier
使用有关?如果是这样,我该如何使用它?
我最后做的基本上只是使用 .animateContentSize()
修饰符。
@Compose
fun ExpandingConfirmButton(onConfirm: () -> Unit) {
// expanded state of the button
val (expanded, setExpanded) = remember { mutableStateOf(false) }
Button(
modifier = Modifier.animateContentSize(), // do this
onClick = {
// only fire the action after two taps
if(expanded) {
onConfirm()
}
setExpanded(!expanded)
}) {
Icon(Icons.Default.Delete)
// only show the text if the button has already been clicked once,
// otherwise just show the icon
if(expanded) {
Text(text = "Delete", softWrap = false)
}
}
}
真的就是这么简单。不要乱用手动宽度、重量或类似的东西。