有没有办法删除App Bar NestedScrollConnection中的空间?

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

我正在尝试使用自定义 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
2个回答
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

注:

当内容滚动时,这不会使

CenterAlignedTopAppBar
颜色产生动画效果。


0
投票

我发现了问题,我只是在我的 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 的高度,并且在它保持不变之前。

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