我正在尝试使用自定义 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)
}
}
输出: