Search code examples
android-jetpack-composeoffsetbottomnavigationviewappbar

Scaffold body behind AppBar in Android Jetpack Compose?


I want to extend my Scaffold body behind the AppBar because of the curve in the bottom right corner:

enter image description here

I tried Modifier.offset(y = (-25).dp). It works fine, but the BG image not fills the area behind the bottom navbar anymore:

 Scaffold( topBar = { ... }, ) 
        { padding ->
            Box(
                Modifier.padding(padding),
                contentAlignment = Alignment.TopCenter
            ) {
                Box(
                    modifier = Modifier
                        .fillMaxSize()
                        .offset(y = (-25).dp),  // BG image behind AppBar
                ) {
                    Image(
                        modifier = Modifier.fillMaxSize(),
                        painter = painterResource(R.drawable.bg),
                        contentDescription = null,
                        contentScale = ContentScale.FillBounds
                    )
                }

enter image description here

How can I do both?


Solution

  • You can use Modifier.graphicsLayer {scaleY = // scale ratio greater than 1f}

    But this option requires you to be able to find exact ratio(height of Scaffold / height of Box with Image) you need to use a way for finding height of both Scaffold and Box then you can scale exactly.

    @Composable
    private fun BoxSample() {
        BoxWithConstraints(modifier = Modifier.fillMaxSize()) {
    
            val parentHeight = maxHeight
            Scaffold(
                topBar = {
                    Box(
                        modifier = Modifier
                            .fillMaxWidth()
                            .height(50.dp)
                            .background(Color.Black),
                        contentAlignment = Alignment.Center
                    ) {
                        Text("TITLE", fontSize = 20.sp, color = Color.White)
                    }
                }
            )
            { padding ->
                BoxWithConstraints(
                    Modifier.padding(padding),
                    contentAlignment = Alignment.TopCenter
                ) {
                    val childHeight = this.maxHeight
    
                    val scaleY = parentHeight.value / childHeight.value
                    Box(
                        modifier = Modifier
                            .fillMaxSize()
                            .graphicsLayer {
                                this.scaleY = scaleY
                            }
                    ) {
                        Image(
                            modifier = Modifier.fillMaxSize(),
                            painter = painterResource(R.drawable.bg),
                            contentDescription = null,
                            contentScale = ContentScale.FillBounds
                        )
                    }
                }
            }
        }
    }
    

    Second option is placing your appbar not inside topBar property of Scaffold but inside a Box in content.

    @Composable
    private fun Sample() {
        Box(
            Modifier.padding(padding),
            contentAlignment = Alignment.TopCenter
        ) {
            Box(
                modifier = Modifier
                    .fillMaxSize(),
            contentAlignment = Alignment.TopStart
    
            ) {
                Image(
                    modifier = Modifier.fillMaxSize(),
                    painter = painterResource(R.drawable.bg),
                    contentDescription = null,
                    contentScale = ContentScale.FillBounds
                )
            }
            TopAppbar()
        }
    }
    

    Third option is putting Box with Image in topBar of Scaffold