BottomSheetScaffold 的工作表在重组时会自动扩展

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

在 Jetpack Compose 中,我有一个包含一些内容的

BottomSheetScaffold
。该内容是从 ViewModel 中观察到的,如下所示:

BottomSheetScaffold(
    sheetContent = { SheetContent(sheetData = viewModel.sheetData) }
) {}

因此,每当

viewModel.sheetData
发生变化时,就会触发重组。每当发生这种情况时,底部工作表就会自动展开。这是一个错误还是一个功能?我可以禁用这个吗?我正在使用最新版本:1.1.0-alpha01

编辑:这是一个使用

LaunchedEffect
而不是 ViewModel 的示例。

@OptIn(ExperimentalMaterialApi::class)
@Preview
@Composable
fun HomeScreen() {
    var addSheetData by remember { mutableStateOf(false) }

    LaunchedEffect(true) {
        delay(2000)
        addSheetData = true
    }

    BottomSheetScaffold(sheetContent = {
        if (addSheetData) {
            Column {
                Text(text = "Text1", fontSize = 36.sp)
                Text(text = "Text2", fontSize = 36.sp)
                Text(text = "Text3", fontSize = 36.sp)
                Text(text = "Text4", fontSize = 36.sp)
                Text(text = "Text5", fontSize = 36.sp)
            }
        }
    }, sheetBackgroundColor = Color.LightGray) {}
}

包含 5 个文本的工作表会自动展开。

android-jetpack-compose material-components-android bottom-sheet
5个回答
6
投票

这似乎是一个错误。
目前(

1.0.x
1.1.0-alpha01
)当
sheetContentHeight
<
sheetPeekHeight
时,就会发生这种情况。
在这种情况下,即使不显示内容表,也会产生
scaffoldState.bottomSheetState
结果
expanded

您可以在代码中轻松验证它:

sheetBackgroundColor = if (scaffoldState.bottomSheetState.isCollapsed) Color.LightGray else Color.Yellow

addSheetData == false
时,背景颜色变为
Yellow
。当您重新组合可组合项时,由于状态已展开,因此内容表已完全展开。

作为解决方法,您可以使用类似以下内容:

  sheetContent = { 
        if (!addSheetData){
            Box(Modifier.fillMaxWidth().height(60.dp))
        }    

        if (addSheetData) {
            Column {
                Text(text = "Text1", fontSize = 36.sp)
                Text(text = "Text2", fontSize = 36.sp)
                Text(text = "Text3", fontSize = 36.sp)
                Text(text = "Text4", fontSize = 36.sp)
                Text(text = "Text5", fontSize = 36.sp)
            }
        }
  }

2
投票

这似乎是

BottomSheetScaffold
的一个错误。不过,您可以尝试替代方案,那就是
ModalBottomSheetLayout
。有关此可组合项的更多信息可以在此处找到。


1
投票

尝试添加初始值:

val bottomSheetScaffoldState = rememberBottomSheetScaffoldState(
        bottomSheetState = BottomSheetState(
            initialValue = BottomSheetValue.Collapsed,
        )
    )

0
投票

我设法通过创建一个管理脚手架状态的自定义状态来解决这个问题,并根据我的自定义状态显示工作表内容,因为脚手架状态始终返回到

Expanded

这是我的解决方案:

@OptIn(ExperimentalMaterialApi::class)
@Composable
fun CustomBottomSheet(
    customBottomSheetState: CustomBottomSheetState = rememberCustomBottomSheetState(remember { CustomBottomSheetState() }),
    topBar: (@Composable () -> Unit)? = null,
    sheetContent: @Composable() (ColumnScope.() -> Unit),
    content: @Composable () -> Unit
) {
    val scaffoldState: BottomSheetScaffoldState = rememberBottomSheetScaffoldState()
    customBottomSheetState.scaffoldState = scaffoldState
    // this to handle updating the state when collapsing by swiping the sheet down
    if (scaffoldState.bottomSheetState.isCollapsed) {
        customBottomSheetState.currentValue.value = CustomBottomSheetValue.Collapsed
    }
    BottomSheetScaffold(
        sheetPeekHeight = 0.dp,
        topBar = topBar,
        scaffoldState = scaffoldState,
        sheetShape = BottomSheetShape,
        sheetContent = {
            if (customBottomSheetState.isExpanded()) {
                sheetContent()
            }
        }
    ) {
        Box(Modifier.padding(it)) {
            content()
        }
    }
}

@Stable
@OptIn(ExperimentalMaterialApi::class)
class CustomBottomSheetState constructor(
    initialValue: MutableState<CustomBottomSheetValue> = mutableStateOf(CustomBottomSheetValue.Collapsed)
) {
    var currentValue = initialValue
    var scaffoldState: BottomSheetScaffoldState? = null
    suspend fun expand() {
        scaffoldState?.bottomSheetState?.expand()
        currentValue.value = CustomBottomSheetValue.Expanded
    }

    suspend fun collapse() {
        scaffoldState?.bottomSheetState?.collapse()
        currentValue.value = CustomBottomSheetValue.Collapsed
    }
    fun isCollapsed(): Boolean {
        return this.currentValue.value == CustomBottomSheetValue.Collapsed
    }

    fun isExpanded(): Boolean {
        return this.currentValue.value == CustomBottomSheetValue.Expanded
    }
}

enum class CustomBottomSheetValue {
    Expanded, Collapsed;
}

@Composable
fun rememberCustomBottomSheetState(bottomSheetState: CustomBottomSheetState = CustomBottomSheetState()) =
    remember(bottomSheetState) { bottomSheetState }

这就是它的用法:

    val bottomSheetState = rememberCustomBottomSheetState()
    CustomBottomSheet(topBar = {
        // topbar
    }, customBottomSheetState = bottomSheetState, sheetContent = {
            // sheet
        }) {
        // screen
    }

您可以修改参数以包含所有

BottomSheetScaffold
参数。


0
投票

我无法修复不需要的重组。发生的事情是每当它重新组合时,它就会回到

initialValue: SheetValue.
就我而言,我使用的是
rememberStandardBottomSheetState
,它的默认值为
initialValue: SheetValue = PartiallyExpanded
,所以每次它都会重新组合我的 BottomSheet“最小化”...

我的解决方法是将初始值设置为可保存状态,并在状态发生变化时更新它,以便在重新组合时,bottomSheet 保持其状态。

var sheetState by remember { mutableStateOf(SheetValue.PartiallyExpanded) }

如果您的bottomSheet只能通过“拖动”进行更改,您可以通过在

confirmValueChange
中找到的
rememberStandardBottomSheetState
拦截状态更改,在我的情况下,我还可以通过dragHandle onClicks展开()/“最小化”()。您可以从我的代码中获得启发:

    @Composable
    private fun StickyBottomSheet(
        content: @Composable ColumnScope.() -> Unit,
        title: String? = null,
        onStateChange: (BottomSheetState) -> Unit = {}
    ){
    val scope = rememberCoroutineScope()
    var sheetState by remember { mutableStateOf(SheetValue.PartiallyExpanded) }
    val state = rememberStandardBottomSheetState(
        initialValue = sheetState,
        confirmValueChange = { sheetValue ->
            sheetState = sheetValue
            when (sheetValue) {
                SheetValue.Hidden -> false

                SheetValue.Expanded -> {
                    onStateChange(BottomSheetState.Expanded)
                    true
                }

                SheetValue.PartiallyExpanded -> {
                    onStateChange(BottomSheetState.Minimised)
                    true
                }
            }
        }
    )
    val scaffoldState = rememberBottomSheetScaffoldState(bottomSheetState = state)
    BottomSheetScaffold(
        sheetContent = content,
        scaffoldState = scaffoldState,
        sheetShadowElevation = 8.dp,
        sheetDragHandle = {
            DragHandle(
                title = title,
                onClick = {
                    scope.launch {
                        if (scaffoldState.bottomSheetState.currentValue == SheetValue.PartiallyExpanded) {
                            sheetState = SheetValue.Expanded
                            scaffoldState.bottomSheetState.expand()
                            onStateChange(BottomSheetState.Expanded)
                        } else {
                            scaffoldState.bottomSheetState.show()
                            onStateChange(BottomSheetState.Dismissed)
                        }
                    }
                },
                expanded = scaffoldState.bottomSheetState.currentValue == SheetValue.Expanded
            )
        }
    ) {

    }
}

@Composable
private fun DragHandle(title: String?, onClick: () -> Unit = {}, expanded: Boolean){
Surface(
    modifier = Modifier.height(56.dp)
) {
    AnimatedVisibility(visible = expanded, enter = fadeIn(), exit = fadeOut()) {
        Box(modifier = Modifier.fillMaxWidth()) {
            Box(
                Modifier
                    .padding(top = 16.dp)
                    .size(width = 32.dp, height = 4.dp)
                    .background(wjColorScheme.outline)
                    .align(Alignment.TopCenter)
            )
            IconButton(
                modifier = Modifier.align(Alignment.CenterEnd),
                onClick = { onClick() },
                content = { Icon(R.drawable.ic_close_24 )})
        }
    }
    AnimatedVisibility(!expanded, enter = fadeIn(), exit = fadeOut()) {
        Row(modifier = Modifier.clickable { onClick() }
        ) {
            ListItem(
                leadingContent = { Icon(R.drawable.ic_add_24) },
                text2 = title
            )
        }
    }
}

}

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