简体   繁体   English

使用脚手架 android 折叠喷气背包中的顶部应用程序栏

[英]Collapsing top app bar in jetpack compose using scaffold android

I looked at many questions about collapsing of Top App Bar in jetpack compose android eg Jetpack Compose collapsing toolbar , Plants details view , etc. But none of the tutorials/examples are using the Scaffold.我查看了许多有关在 Jetpack compose android 中折叠 Top App Bar 的问题,例如Jetpack Compose 折叠工具栏植物详细信息视图等。但没有一个教程/示例使用脚手架。 Hence this question.因此这个问题。

Following the example given in the android documentation , I changed it a bit to use it with a scaffold.按照 android 文档中给出的示例,我对其进行了一些更改以将其与脚手架一起使用。

// here we use LazyColumn that has a build-in nested scroll, but we want to act like a
// parent for this LazyColumn and participate in its nested scroll.
// Let's make a collapsing toolbar for LazyColumn
val toolbarHeight = 48.dp
val toolbarHeightPx = with(LocalDensity.current) { toolbarHeight.roundToPx().toFloat() }
// our offset to collapse toolbar
val toolbarOffsetHeightPx = remember { mutableStateOf(0f) }
// now, let's create connection to the nested scroll system and listen to the scroll
// happening inside child LazyColumn
val nestedScrollConnection = remember {
    object : NestedScrollConnection {
        override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset {
            // try to consume before LazyColumn to collapse toolbar if needed, hence pre-scroll
            val delta = available.y
            val newOffset = toolbarOffsetHeightPx.value + delta
            toolbarOffsetHeightPx.value = newOffset.coerceIn(-toolbarHeightPx, 0f)
            // here's the catch: let's pretend we consumed 0 in any case, since we want
            // LazyColumn to scroll anyway for good UX
            // We're basically watching scroll without taking it
            return Offset.Zero
        }
    }
}

Scaffold(
    topBar = {
        TopAppBar(
            modifier = Modifier
                .height(toolbarHeight)
                .offset { IntOffset(x = 0, y = toolbarOffsetHeightPx.value.roundToInt()) },
            title = { Text("toolbar offset is ${toolbarOffsetHeightPx.value}") }
        )
    }
) {
    Box(
        Modifier
            .fillMaxSize()
            // attach as a parent to the nested scroll system
            .nestedScroll(nestedScrollConnection)
    ) {
        // our list with build in nested scroll support that will notify us about its scroll
        LazyColumn {
            items(100) { index ->
                Text("I'm item $index", modifier = Modifier
                    .fillMaxWidth()
                    .padding(16.dp))
            }
        }
    }
}

The output is NOT as expected. output 不符合预期。 The Top App Bar tends to move up but the height of the TopBar in the scaffold remains the same and so the list starts to disappear at the height of the Top App Bar. Top App Bar 倾向于向上移动,但脚手架中 TopBar 的高度保持不变,因此列表在 Top App Bar 的高度处开始消失。

So my question is how to calculate the height of the top app bar so that it changes according to the offset.所以我的问题是如何计算顶部应用栏的高度,以便它根据偏移量发生变化。

I tried我试过了

height - y offset value

But that does not work.但这不起作用。

Actually, the Scaffold does not make much difference in the answer that I mentioned in the comment above.实际上, Scaffold对我在上面评论中提到的答案没有太大影响。 See the code below.请参阅下面的代码。

You just need to adjust for your needs...你只需要根据自己的需要进行调整...

@ExperimentalFoundationApi
@Composable
fun CollapsingEffectScreen() {
    val items = (1..100).map { "Item $it" }
    val lazyListState = rememberLazyListState()
    var scrolledY = 0f
    var previousOffset = 0
    Scaffold {
        LazyColumn(
            Modifier
                .fillMaxSize()
                .padding(it),
            lazyListState,
        ) {
            item {
                TopAppBar(
                    Modifier
                        .graphicsLayer {
                            scrolledY += lazyListState.firstVisibleItemScrollOffset - previousOffset
                            translationY = scrolledY * 0.5f
                            previousOffset = lazyListState.firstVisibleItemScrollOffset
                        }
                        .height(240.dp)
                        .fillMaxWidth()
                ) {
                    Image(
                        modifier = Modifier.fillMaxWidth().wrapContentHeight(),
                        painter = painterResource(id = R.drawable.recife),
                        contentDescription = null,
                        contentScale = ContentScale.FillWidth,
                    )
                }
            }
            items(items) {
                Text(
                    text = it,
                    Modifier
                        .background(MaterialTheme.colors.surface)
                        .fillMaxWidth()
                        .padding(8.dp)
                )
            }
        }
    }
}

It could be more ability by using Modifier.nestedScroll and scrollBehavior with Scaffold Compose.通过使用带有Scaffold Compose 的Modifier.nestedScrollscrollBehavior可能会更有能力。

@OptIn(ExperimentalMaterial3Api::class)
@Preview
@Composable
fun TopBarton() {
    val appBarState = rememberTopAppBarState()
    val scrollBehavior = remember { TopAppBarDefaults.enterAlwaysScrollBehavior(appBarState) }
    Scaffold(
        modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
        topBar = {
            SmallTopAppBar(
                title = { Text("TopBarton") },
                navigationIcon = {
                    IconButton(onClick = { /* ... */ }) {
                        Icon(
                            imageVector = Icons.Filled.Menu,
                            contentDescription = null
                        )
                    }
                },
                actions = {
                    IconButton(onClick = { /* ... */ }) {
                        Icon(
                            imageVector = Icons.Filled.Star,
                            contentDescription = null
                        )
                    }
                },
                scrollBehavior = scrollBehavior
            )
        },
        content = { innerPadding ->
            LazyColumn(
                contentPadding = innerPadding,
                verticalArrangement = Arrangement.spacedBy(9.dp)
            ) {
                val list = (0..100).map { it.toString() }
                items(count = list.size) {
                    Text(
                        text = list[it],
                        style = MaterialTheme.typography.bodyLarge,
                        modifier = Modifier
                            .fillMaxWidth()
                            .padding(horizontal = 18.dp)
                    )
                }
            }
        }
    )
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM