有没有办法在 Compose 中删除应用栏 NestedScrollConnection 中的空间?

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

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

android-jetpack-compose nested-scroll
1个回答
0
投票

当您使用

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)
    }
}

输出:

Screen Recording

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