在 Jetpack Compose 中使用权重时如何防止整个 UI 重组?

问题描述 投票:0回答:1

我正在 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()
            )
        }
    }
}

android kotlin android-jetpack-compose android-jetpack
1个回答
0
投票

我认为你需要做出两个改变:

  1. 首先,将以下代码移至“PhonePortraitLayout”可组合项中:

    val expandedStateHandler = remember {
        ExpandedStateHandler()
    }
    
  2. 如果您想防止“CalculatorDisplay”重新组合,请将其移出“PhonePortraitLayout”并将其放置在“CalculatorScreen”中。

© www.soinside.com 2019 - 2024. All rights reserved.