我正在 Jetpack Compose 中构建一个计算器应用程序,并面临重组问题。我的布局包含三个主要组成部分:
CalculatorDisplay
、CalculatorAdvanced
和CalculatorPad
。布局使用权重进行响应式设计。但是,当我使用 isExpanded
切换 CalculatorExpandButton
状态时,整个屏幕会重新组合,而不仅仅是相关组件 (CalculatorAdvanced and CalculatorPad)
。
CalculatorDisplay
进行不必要的重组。CalculatorAdvanced
更改时仅重新组合 CalculatorPad
和 isExpanded
。remember
和 derivedStateOf
: 我将这些应用到 advancedWeight
和 padWeight
来最小化状态更新,但整个 UI 仍然会重新组合。 (也许我做错了)CalculatorExpandButton
会导致整个 PhonePortraitLayout
重新组合。这是布局代码:
@Composable
fun CalculatorScreen(viewModel: CalculatorViewModel = viewModel()) {
val context = LocalContext.current
val activity = context as Activity
val window = activity.window
val windowSizeClass = rememberWindowSizeClass()
val color = MaterialTheme.colorScheme.surfaceColorAtElevation(24.dp).toArgb()
SideEffect {
window.statusBarColor = color
}
val expandedStateHandler = remember {
ExpandedStateHandler()
}
Box(modifier = Modifier.fillMaxSize()) {
when {
/** PHONE */
windowSizeClass.isPhonePortrait -> PhonePortraitLayout(
viewModel = viewModel,
windowSizeClass = windowSizeClass,
expandedStateHandler = expandedStateHandler
)
}
}
}
class ExpandedStateHandler {
var isExpanded by mutableStateOf(false)
private set
fun toggle() {
isExpanded = !isExpanded
}
}
@Composable
fun PhonePortraitLayout(
viewModel: CalculatorViewModel,
windowSizeClass: MyWindowSizeClass,
expandedStateHandler: ExpandedStateHandler
) {
val displayWeight = 0.3337f // Fixed weight for CalculatorDisplay
val advancedWeight = if (expandedStateHandler.isExpanded) 0.1451f else 0.045f
val padWeight = if (expandedStateHandler.isExpanded) 0.4f else 0.5f
Column(
verticalArrangement = Arrangement.spacedBy(8.dp),
modifier = Modifier.padding(bottom = 8.dp)
) {
// Stabilized CalculatorDisplay
Box(
modifier = Modifier
.fillMaxWidth()
.weight(displayWeight)
) {
CalculatorDisplay(
viewModel = viewModel,
modifier = Modifier.fillMaxSize()
)
}
Row(
modifier = Modifier
.fillMaxWidth()
.weight(advancedWeight)
) {
Box(
modifier = Modifier
.weight(3.1f) // Keeps internal proportions
.padding(start = 16.dp, end = 4.dp)
) {
CalculatorAdvanced(
viewModel = viewModel,
windowSizeClass = windowSizeClass,
isExpanded = expandedStateHandler.isExpanded,
modifier = Modifier.fillMaxSize()
)
}
Box(
contentAlignment = Alignment.TopEnd,
modifier = Modifier
.padding(start = 4.dp, end = 16.dp)
.weight(0.56f)
) {
CalculatorExpandButton(
text = if (expandedStateHandler.isExpanded) "Adv" else "Basic",
onClick = { expandedStateHandler.toggle() }
)
}
}
Box(
modifier = Modifier
.fillMaxWidth()
.weight(padWeight)
.padding(horizontal = 16.dp)
) {
CalculatorPad(
viewModel = viewModel,
windowSizeClass = windowSizeClass,
modifier = Modifier.fillMaxSize()
)
}
}
}
我认为你需要做出两个改变:
首先,将以下代码移至“PhonePortraitLayout”可组合项中:
val expandedStateHandler = remember {
ExpandedStateHandler()
}
如果您想防止“CalculatorDisplay”重新组合,请将其移出“PhonePortraitLayout”并将其放置在“CalculatorScreen”中。