Jetpack Compose 折叠工具栏

时间:2021-04-23 09:51:21

标签: android kotlin android-jetpack android-jetpack-compose

我找不到有关此事的任何文档,是否有类似于 Compose 中的 CollapsingToolbar 的内容?

我发现的只是提及它here,但没有关于如何设置它

5 个答案:

答案 0 :(得分:2)

在 Jetpack Compose 中,我通过以下代码实现了折叠工具栏:

@Composable
fun MainScreen(){
    val scrollState = rememberScrollState()
    // parallax effect by offset
    val imageOffset = (-scrollState.value * 0.18f).dp
    Box {
        Image(
            painter = painterResource(id = R.drawable.bg_header),
            contentDescription = null,
            contentScale = ContentScale.FillWidth,
            modifier = Modifier
                .graphicsLayer { translationY = imageOffset }
                .height(240.dp)
                .fillMaxWidth()
        )

        Column(
            Modifier
                .verticalScroll(scrollState)
                .padding(top = 200.dp)
                .background(
                    MaterialTheme.colors.surface,
                    RoundedCornerShape(topStart = 16.dp, topEnd = 16.dp)
                )
                .fillMaxHeight()
                .fillMaxWidth()
                .padding(all = 16.dp)
        ) {
            // Main content here
        }
    }
}

你可以用 LazyColumn 替换 Column 和val scrollState = rememberLazyListState()

答案 1 :(得分:2)

我找到了 Samir Basnet(来自 Kotlin Slack Channel)创建的一个对我有用的解决方案,我希望它可以帮助其他人...

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

结果如下:

enter image description here

答案 2 :(得分:2)

我在 Android 文档中找到了这个,我认为您在问题中链接的文档正在谈论使用嵌套滚动这样做。

val toolbarHeight = 48.dp
    val toolbarHeightPx = with(LocalDensity.current) { toolbarHeight.roundToPx().toFloat() }
    val toolbarOffsetHeightPx = remember { mutableStateOf(0f) }

    val nestedScrollConnection = remember {
        object : NestedScrollConnection {
            override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset {

                val delta = available.y
                val newOffset = toolbarOffsetHeightPx.value + delta
                toolbarOffsetHeightPx.value = newOffset.coerceIn(-toolbarHeightPx, 0f)
                return Offset.Zero
            }
        }
    }
    Box(
        Modifier
            .fillMaxSize()

            .nestedScroll(nestedScrollConnection)
    ) {

        LazyColumn(contentPadding = PaddingValues(top = toolbarHeight)) {
            items(100) { index ->
                Text("I'm item $index", modifier = Modifier
                    .fillMaxWidth()
                    .padding(16.dp))
            }
        }
        TopAppBar(
            modifier = Modifier
                .height(toolbarHeight)
                .offset { IntOffset(x = 0, y = toolbarOffsetHeightPx.value.roundToInt()) },
            title = { Text("toolbar offset is ${toolbarOffsetHeightPx.value}") }
        )
    }

答案 3 :(得分:1)

您可以使用 compose-collapsing-toolbar 库。

安装implementation "me.onebone:toolbar-compose:2.1.0"

Usage - Exemple

预览

以下是库的 Readme.md 中的一些 gif 图像:

jetpack compose collapsing toolbar jetpack compose collapsing toolbar | EnterAlwaysCollapsed jetpack compose collapsing toolbar | ExitUntilCollapsed

答案 4 :(得分:0)

您可以按照 example in the docs 创建一个工具栏,该工具栏会在每次向上/向下滚动时展开/折叠。

要创建仅在列表滚动到顶部时才展开的工具栏,您可以对原始示例稍作修改:

val toolbarHeight = 48.dp
val toolbarHeightPx = with(LocalDensity.current) { toolbarHeight.roundToPx().toFloat() }
var toolbarOffsetHeightPx by remember { mutableStateOf(0f) }
var totalScrollOffsetPx = remember { 0f }

val nestedScrollConnection = remember {
    object : NestedScrollConnection {
        override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset {

            val delta = available.y
            totalScrollOffsetPx += delta
            
            if (totalScrollOffsetPx in -toolbarHeightPx..0f) {
                toolbarOffsetHeightPx = totalScrollOffsetPx
            }

            return Offset.Zero
        }
    }
}

通过这样做,您可以灵活地创建自己的 CollapsibleScaffold,它可以接受 scrollBehaviourappBarLayoutlist 可组合等参数。< /p>

这样,例如,您还可以以编程方式计算应用栏的高度并摆脱大量的样板文件,使您屏幕中使用的代码整洁干净。