Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

599
Visualizações
Jetpack Compose collapsing toolbar

I can't find any doc on the matter, is there something similar to a CollapsingToolbar in Compose?

All I found was a mention of it here, but nothing on how to set it up

over 4 years ago · Hanz Gallego
7 Respostas
Responde à pergunta

0

Jetpack Compose implementation of Material Design 3 includes 4 types of Top App Bars (https://m3.material.io/components/top-app-bar/implementation):

  • CenterAlignedTopAppBar
  • SmallTopAppBar
  • MediumTopAppBar
  • LargeTopAppBar

https://developer.android.com/reference/kotlin/androidx/compose/material3/package-summary

They all have a scrollBehavior parameter, which can be used for collapsing the toolbar. There are 3 basic types of scroll behavior in the library:

  • TopAppBarDefaults.pinnedScrollBehavior
  • TopAppBarDefaults.enterAlwaysScrollBehavior
  • TopAppBarDefaults.exitUntilCollapsedScrollBehavior

https://developer.android.com/reference/kotlin/androidx/compose/material3/TopAppBarDefaults

Note: This API is annotated as experimental at the moment.

Sample usage:

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun Test() {
    val scrollBehavior = remember { TopAppBarDefaults.enterAlwaysScrollBehavior() }
    Scaffold(
        modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
        topBar = {
            MediumTopAppBar(
                title = { Text(text = "Scroll Behavior Test") },
                navigationIcon = {
                    IconButton(onClick = { /*TODO*/ }) {
                        Icon(imageVector = Icons.Default.Menu, contentDescription = "")
                    }
                },
                scrollBehavior = scrollBehavior
            )
        }
    ) {
        LazyColumn(modifier = Modifier.fillMaxWidth()) {
            items((1..50).toList()) { item ->
                Text(modifier = Modifier.padding(8.dp), text = "Item $item")
            }
        }
    }
}
over 4 years ago · Hanz Gallego Relatório

0

Compose-collapsing-toolbar A simple implementation of CollapsingToolbarLayout for Jetpack Compose

https://github.com/onebone/compose-collapsing-toolbar

over 4 years ago · Hanz Gallego Relatório

0

You can follow the example in the docs to create a toolbar which expands/collapses on every scroll up/down.

To create a toolbar which expands only when the list is scrolled to the top, you can make a slight adaptation to the original example:

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

By doing so, you have a flexibility which would enable you to create your own CollapsibleScaffold which could accept params like scrollBehaviour, appBarLayout and list composables etc.

That way, for instance, you could also programmatically calculate the height of the app bar and get rid of the high amount of boilerplate, making the code used in your screens neat and clean.

over 4 years ago · Hanz Gallego Relatório

0

You can use the compose-collapsing-toolbar library.

Instalation : implementation "me.onebone:toolbar-compose:2.1.0"

Usage - Exemple

Preview

Here are some gif images from the Readme.md of the library:

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

over 4 years ago · Hanz Gallego Relatório

0

In the Jetpack Compose, I implemented collapsing toolbar by the following code:

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

You can replace Column with LazyColumn and val scrollState = rememberLazyListState()

over 4 years ago · Hanz Gallego Relatório

0

I found this in Android docs, I think the documentation you linked in the question is talking about doing it like this with nested scrolling.

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}") }
        )
    }
over 4 years ago · Hanz Gallego Relatório

0

I found a solution created by Samir Basnet (from Kotlin Slack Channel) which was useful for me, I hope it helps someone else...

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

Here is the result:

enter image description here

over 4 years ago · Hanz Gallego Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda