Home > Mobile >  How to programatically set peekHeight for Android Compose BackdropScaffold
How to programatically set peekHeight for Android Compose BackdropScaffold

Time:06-30

How can i programmatically set the peekHeight of androidx.compose.material.BackdropScaffold, so that the frontlayer is exactly underneath the appBar?

I have this code to build the app bar

@Composable
fun MyAppBar(backdropRevealed: Boolean, onBackdropReveal: (Boolean) -> Unit = {}) {

        var size by remember { mutableStateOf(IntSize.Zero) }
    
        SmallTopAppBar(
            modifier = Modifier.onSizeChanged { size = it },
            title = {
                Row(
                    modifier = Modifier.fillMaxWidth(),
                    horizontalArrangement = Arrangement.Start,
                    verticalAlignment = Alignment.CenterVertically
                ) {
                    Box(
                        Modifier
                            .width(48.dp)
                            .toggleable(
                                value = backdropRevealed,
                                onValueChange = { onBackdropReveal(it) },
                                indication = rememberRipple(bounded = false, radius = 56.dp),
                                interactionSource = remember { MutableInteractionSource() }
                            ),
                        contentAlignment = Alignment.CenterStart
                    ) {
                        AnimatedContent(
                            targetState = backdropRevealed,
                            transitionSpec = {
                                if (targetState) {
                                    fadeIn(animationSpec = tween(durationMillis = 240, delayMillis = 120, easing = LinearEasing)) with
                                            fadeOut(animationSpec = tween(durationMillis = 120, easing = LinearEasing))
                                } else {
                                    // Reveal to conceal
                                    fadeIn(animationSpec = tween(durationMillis = 180, delayMillis = 90, easing = LinearEasing)) with
                                            fadeOut(animationSpec = tween(durationMillis = 90, easing = LinearEasing))
                                }.using(SizeTransform(clip = false))
                            },
                            contentAlignment = Alignment.CenterStart
                        ) { revealed ->
                            if (revealed) {
                                Icon(
                                    Icons.Default.Close,
                                    contentDescription = "Close"
                                )
                            } else {
                                Icon(
                                    Icons.Default.Menu,
                                    contentDescription = "Menu"
                                )
                            }
                        }
                    }
                    Text(
                        text = "My App",
                        style = MaterialTheme.typography.titleMedium,
                        color = MaterialTheme.colorScheme.onSurface
                    )
                }
            },
            actions = {
                IconButton(onClick = { Timber.e("Display Overflow app bar actions") }) {
                    Icon(
                        imageVector = Icons.Rounded.MoreVert,
                        contentDescription = "Localized description"
                    )
                }
            }
        )
    }

and my variable size does contain the actual height

i cannot see how to pass this to my BackdropScaffold to set its peekHeight

heres the Backdrop code

val myAppBar: @Composable () -> Unit = {
    MyAppBar(
        backdropRevealed = backdropRevealed,
        onBackdropReveal = {
            if (!scaffoldState.isAnimationRunning) {
                backdropRevealed = it
                scope.launch {
                    if (scaffoldState.isConcealed) {
                        scaffoldState.reveal()
                    } else {
                        scaffoldState.conceal()
                    }
                }
            }
        })
}

BackdropScaffold(
    scaffoldState = scaffoldState,
    gesturesEnabled = false,
    appBar = myAppBar,
    backLayerBackgroundColor = MaterialTheme.colorScheme.secondary,
    backLayerContentColor = MaterialTheme.colorScheme.onSecondary,
    backLayerContent = { ShowcaseBackLayerContent() },
    frontLayerContent = { ShowcaseFrontLayerContent() },
    frontLayerScrimColor = Color.Unspecified,
    peekHeight = 70.dp
) {

}

how can i programmatically set peekHeight to the size.height?

CodePudding user response:

Your code works when you get size from Modifier.onSizeChanged and pass it via a callback to your BackdropScaffold

@Composable
private fun MyComposable() {

    val backdropScaffoldState =
        rememberBackdropScaffoldState(initialValue = BackdropValue.Revealed)

    var peekHeight by remember { mutableStateOf(BackdropScaffoldDefaults.PeekHeight) }
    val density = LocalDensity.current

    BackdropScaffold(
        appBar = {
            MyAppBar(true,
                onSizeChanged = {
                    with(density) {
                        peekHeight = it.height.toDp()
                    }
                },
                onBackdropReveal = {

                }
            )

        },
        scaffoldState = backdropScaffoldState,
        peekHeight = peekHeight,
        backLayerContent = {
            BackLayerContent()
        },

        frontLayerContent = {
            FrontLayerContent()
        }
    ) {

    }
}

@Composable
fun FrontLayerContent() {
    Column(modifier = Modifier.fillMaxSize()) {
        Text("Back Layer", fontSize = 20.sp)
    }
}

@Composable
fun BackLayerContent() {
    Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
        Text("Back Layer", fontSize = 40.sp, color = Color.White)
    }
}

@OptIn(ExperimentalAnimationApi::class)
@Composable
fun MyAppBar(
    backdropRevealed: Boolean,
    onSizeChanged: (IntSize) -> Unit,
    onBackdropReveal: (Boolean) -> Unit = {}
) {

    var size by remember { mutableStateOf(IntSize.Zero) }

    SmallTopAppBar(
        modifier = Modifier
            .wrapContentHeight()
            .onSizeChanged {
                size = it
                onSizeChanged(it)
                println("           
  • Related