我正在尝试使用自定义 NestedScrollConnection 折叠应用程序栏,但当我滚动时,它会在应用程序栏位置腾出空间。滚动时App Bar会上升,但App Bar背景中的App Bar空间没有上升?
我的自定义 NestedScrollConnection 类:
class CollapsingAppBarNestedScrollConnection(
val appBarMaxHeight: Int,
) : NestedScrollConnection {
var appBarOffset by mutableIntStateOf(0)
private set
override fun onPreScroll(
available: Offset,
source: NestedScrollSource,
): Offset {
val delta = available.y.roundToInt()
val newsOffset = appBarOffset + delta
val previousOffset = appBarOffset
appBarOffset = newsOffset.coerceIn(
-appBarMaxHeight,
0
)
val consumed = appBarOffset - previousOffset
return Offset(0f, consumed.toFloat())
}
}
我的用户界面:
val density = LocalDensity.current
val appBarMaxHeight = with(density) { (70).dp.roundToPx() }
val connection = remember(appBarMaxHeight) {
CollapsingAppBarNestedScrollConnection(appBarMaxHeightPx)
}
Scaffold(
topBar = {
TopAppBar(
title = {
Text("Top App Bar")
},
modifier = Modifier
.offset { IntOffset(0, connection.appBarOffset) }
)
},
modifier = Modifier
.fillMaxSize()
.nestedScroll(connection)
) {
// Content
}
offset
修饰符时,可组合项最初所在的空间仍然保留。这是因为
它避免了偏移量变化时的重新组合,并且还添加了一个图形层,可以防止偏移量变化时不必要的上下文重绘。
因此,偏移量应用于另一层,并且实际上不会影响可组合层次结构。这意味着您不能将
TopAppBar
最初用于其他可组合项的空间使用。
要实现此目的,您通常会使用默认的
NestedScrollConnection
,例如 TopAppBarDefaults.enterAlwaysScrollBehavior
。
如果您确实需要自定义
NestedScrollConnection
TopAppBar
来在滚动时将 shift 移出屏幕,请使用 height
修改器与 wrapContent
一起实现此操作:
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun MyCollapsibleTopAppBarDemo() {
val density = LocalDensity.current
val myNestedScrollConnection = remember {
MyNestedScrollConnection(TopAppBarDefaults.TopAppBarExpandedHeight.dpToPx(density))
}
Scaffold(
modifier = Modifier
.fillMaxSize()
.nestedScroll(myNestedScrollConnection),
topBar = {
CenterAlignedTopAppBar(
modifier = Modifier
.height(myNestedScrollConnection.currentHeaderHeightPx.toInt().pxToDp(density))
.wrapContentHeight(Alignment.Bottom, true),
colors = TopAppBarDefaults.centerAlignedTopAppBarColors(
containerColor = Color.LightGray
),
title = {
Text("Demonstration")
}
)
}
) { innerPadding ->
LazyColumn(
modifier = Modifier
.fillMaxSize()
.padding(innerPadding)
) {
items(50) { item ->
Text("Item $item", modifier = Modifier.padding(16.dp))
}
}
}
}
fun Dp.dpToPx(density: Density) = with(density) { [email protected]() }
fun Int.pxToDp(density: Density) = with(density) { [email protected]() }
像这样更新您的自定义
NestedScrollConnection
:
class MyNestedScrollConnection(
val appBarMaxHeight: Float,
) : NestedScrollConnection {
var currentHeaderHeightPx by mutableFloatStateOf(appBarMaxHeight)
private set
override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset {
val delta = available.y
val newHeaderHeightPx = currentHeaderHeightPx + delta
val previousHeaderHeightPx = currentHeaderHeightPx
currentHeaderHeightPx = newHeaderHeightPx.coerceIn(0f, appBarMaxHeight)
val consumed = currentHeaderHeightPx - previousHeaderHeightPx
return Offset(x = 0f, y = consumed)
}
}
输出:
注:
当内容滚动时,这不会使
CenterAlignedTopAppBar
颜色产生动画效果。
我发现了问题,我只是在我的 TopAppBar 中添加高度修改器,如下所示:-
// Top Bar Scroll Connection
val topBarMaxHeight: Int = with(density) { (30).dp.roundToPx() }
val topBarScrollConnection: CollapsingAppBarNestedScrollConnection =
remember(topBarMaxHeight) {
CollapsingAppBarNestedScrollConnection(topBarMaxHeight)
}
CenterAlignedTopAppBar(
title = {
Text(
text = "Top App Bar",
)
},
navigationIcon = {
IconButton(onClick = {
scope.launch {
drawerState.open()
}
}) {
Icon(
imageVector = Icons.Default.Menu,
contentDescription = "Icon for Navigation Drawer",
)
}
},
colors = TopAppBarDefaults.topAppBarColors(
containerColor = Color.Transparent,
scrolledContainerColor = Color.Transparent
),
modifier = Modifier
.statusBarsPadding()
.then(
with(density) {
Modifier
.height( // I Add this Height
(topBarMaxHeight + topBarScrollConnection.appBarOffset).toDp()
)
}
)
.offset { IntOffset(0, topBarScrollConnection.appBarOffset) }
)
我添加高度,这样当我滚动时,它就会移动 TopAppBar 的高度,并且在它保持不变之前。