我想动态更改底部片材折叠中相对于底部片材的内容高度,如下所示:
这是我到目前为止所尝试过的: `
val bottomSheetState = rememberBottomSheetState(initialValue =BottomSheetValue.Expanded )
val bottomSheetScaffoldState= rememberBottomSheetScaffoldState(
bottomSheetState = bottomSheetState)
val heightPixels= LocalContext.current.resources.displayMetrics.heightPixels
BottomSheetScaffold(
modifier = Modifier.fillMaxSize()
sheetPeekHeight = 68.dp,
scaffoldState = bottomSheetScaffoldState,
sheetContent = {
/*
sheet content
*/
}) {
Box(modifier = Modifier
.fillMaxWidth()
.fillMaxHeight(((bottomSheetState.offset.value)
/ (heightPixels)).let { if (it == 0f) 1f else it })
) {
/*
content
*/
}
}
但它依赖于系统高度(以像素为单位),并且每次 Bottom Sheet 的高度发生变化时,其内容的框都会重新组合
最佳答案
您可以使用 Modifier.onPlaced/onSizeChanged/onGloballyPositioned
和 BoxWithConstaints
内 BottomSheetScaffold
的总高度获取内容高度并获取高度与
动态内容高度示例
@OptIn(ExperimentalMaterialApi::class)
@Preview
@Composable
private fun BottomSheetScaffoldHeightSample() {
val scaffoldState = rememberBottomSheetScaffoldState()
var sheetPeekHeight by remember {
mutableStateOf(0.dp)
}
val density = LocalDensity.current
BoxWithConstraints {
val parentHeight = maxHeight
SideEffect {
println("Parent is recomposing...")
}
BottomSheetScaffold(
modifier = Modifier.fillMaxSize().drawWithContent {
if (sheetPeekHeight != 0.dp) {
drawContent()
}
},
sheetPeekHeight = sheetPeekHeight,
scaffoldState = scaffoldState,
drawerShape = RoundedCornerShape(16.dp),
sheetContent = {
SideEffect {
println("SheetContent. recomposing...")
}
Box(
modifier = Modifier
.onPlaced {
if (sheetPeekHeight == 0.dp) {
sheetPeekHeight = with(density) {
it.size.height.toDp()
}
}
}
.fillMaxWidth()
.height(200.dp)
.background(Color.Green)
) {
Text(
text = "sheetContent",
color = Color.White,
fontSize = 60.sp
)
}
},
content = {
SideEffect {
println("Content recomposing...")
}
Box(
modifier = Modifier
.fillMaxWidth()
.height(maxHeight - sheetPeekHeight)
.background(Purple400),
contentAlignment = Alignment.Center
) {
Text(
text = "Content",
color = Color.White,
fontSize = 60.sp
)
}
}
)
}
}
您也可以在此处使用下面的 subComposeLayout 方法,您只需添加sheetContent作为主要内容
您还可以根据内容设置工作表高度,如下所示
动态纸张高度示例
@OptIn(ExperimentalMaterialApi::class)
@Preview
@Composable
private fun BottomSheetScaffoldHeightSample() {
val scaffoldState = rememberBottomSheetScaffoldState()
var sheetPeekHeight by remember {
mutableStateOf(0.dp)
}
val density = LocalDensity.current
BoxWithConstraints {
val parentHeight = maxHeight
BottomSheetScaffold(
modifier = Modifier.fillMaxSize().drawWithContent {
if (sheetPeekHeight != 0.dp) {
drawContent()
}
},
sheetPeekHeight = sheetPeekHeight,
scaffoldState = scaffoldState,
drawerShape = RoundedCornerShape(16.dp),
sheetContent = {
SideEffect {
println("SheetContent. recomposing...")
}
LazyColumn(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.spacedBy(16.dp)
) {
items(100) {
Text(
text = "Row $it",
fontSize = 20.sp,
modifier = Modifier
.shadow(2.dp)
.background(Color.White)
.fillMaxWidth()
.padding(16.dp)
)
}
}
},
content = {
SideEffect {
println("Content recomposing...")
}
Box(
modifier = Modifier.fillMaxWidth()
.onPlaced {
if (sheetPeekHeight == 0.dp) {
sheetPeekHeight = with(density) {
parentHeight - it.size.height.toDp()
}
}
}
.background(Purple400)
.padding(48.dp),
contentAlignment = Alignment.Center
) {
Text(
text = "Content",
color = Color.White,
fontSize = 60.sp
)
}
}
)
}
}
但是,这将安排在 BoxWithConstaints 范围或任何其他范围和内容中进行重组,因为我们使用 MutableState 更改高度,以免遇到可以使用的内容高度跳跃
Modifier.drawContent
如上例所示。
其他选项是使用 SubcomposeLayout (如本答案所示)来获取准确的高度,而无需父级重组。
https://stackoverflow.com/a/73357119/5457853
@Composable
fun DimensionSubcomposeLayout(
modifier: Modifier = Modifier,
mainContent: @Composable () -> Unit,
dependentContent: @Composable (Dp) -> Unit
) {
SubcomposeLayout(
modifier = modifier
) { constraints: Constraints ->
// Subcompose(compose only a section) main content and get Placeable
val mainPlaceables: List<Placeable> = subcompose(SlotsEnum.Main, mainContent)
.map {
it.measure(constraints.copy(minWidth = 0, minHeight = 0))
}
var maxWidth = 0
var maxHeight = 0
mainPlaceables.forEach { placeable: Placeable ->
maxWidth += placeable.width
maxHeight = placeable.height
}
val dependentPlaceables: List<Placeable> = subcompose(SlotsEnum.Dependent) {
dependentContent((constraints.maxHeight-maxHeight).toDp())
}
.map { measurable: Measurable ->
measurable.measure(constraints)
}
// This are for Modifier.fillMaxSize if you wish to use with other modifiers
// you need check Constraints bounds and vertical scroll
layout(constraints.maxWidth, constraints.maxHeight) {
dependentPlaceables.forEach { placeable: Placeable ->
placeable.placeRelative(0, 0)
}
}
}
}
enum class SlotsEnum { Main, Dependent }
并将其用作
@OptIn(ExperimentalMaterialApi::class)
@Preview
@Composable
private fun BottomSheetScaffoldHeightSample2() {
val scaffoldState = rememberBottomSheetScaffoldState()
val content = @Composable {
Box(
modifier = Modifier.fillMaxWidth()
.background(Purple400)
.padding(48.dp),
contentAlignment = Alignment.Center
) {
SideEffect {
println("Content recomposing...")
}
Text(
text = "Content",
color = Color.White,
fontSize = 60.sp
)
}
}
DimensionSubcomposeLayout(
modifier = Modifier.fillMaxSize(),
mainContent = content
) { sheetPeekHeight: Dp ->
SideEffect {
println("Parent is recomposing...")
}
BottomSheetScaffold(
modifier = Modifier.fillMaxSize(),
sheetPeekHeight = sheetPeekHeight,
scaffoldState = scaffoldState,
drawerShape = RoundedCornerShape(16.dp),
sheetContent = {
SideEffect {
println("SheetContent. recomposing...")
}
LazyColumn(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.spacedBy(16.dp)
) {
items(100) {
Text(
text = "Row $it",
fontSize = 20.sp,
modifier = Modifier
.shadow(2.dp)
.background(Color.White)
.fillMaxWidth()
.padding(16.dp)
)
}
}
},
content = {
content()
}
)
}
}
关于android - 使用底部片材支架中的底部片材调整内容高度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74412989/