如何在JetPack组成中设置Snackbar的动态位置?

发布于 2025-02-06 10:15:31 字数 1246 浏览 2 评论 0 原文

我有一个带有navhost的脚手架作为其内容。 NAVHOST主机2个屏幕。一个屏幕包含底部navigationbar和另一个屏幕没有。

如果没有底部记录,则如何显示创建一个可以在屏幕底部显示的零食栏,该小吃栏在屏幕底部显示,但如果屏幕包含底部navigationView,则添加了高度=底部的底板=底部navigationHeight?

以下是我的主要内容:


@Composable
fun MainScreen() {
    val navController = rememberNavController()
    val scaffoldState = rememberScaffoldState()
    Scaffold(
        scaffoldState = scaffoldState
    ) {
        NavHost(navController = navController, "first") {
            composable("first") {
                FirstScreen()
            }
            composable("second") {
                SecondScreen()
            }
        }

    }
}

我的第一个屏幕。

// No bottom navigation
@Composable
fun FirstScreen() {
    Text("Hello World")
}

我的第二个屏幕:

// Contains bottom nav
@Composable
fun SecondScreen() {
    Scaffold(bottomBar = { MyBottomBar() }) {

    }
}

现在,我可以使用CompositionLocal将SnackBarhostState从脚手架状态发送到所有屏幕。但是,我希望第一个屏幕显示不带底部填充的小吃栏和第二个屏幕,以显示带有底部Navview的填充物的小吃棒。

如何达到Snackbar的动态位置?

PS这是我问题的简化版本。我有大约6-7个屏幕,用于我的主饰物,带有底部导航的屏幕许多屏幕。

I have a Scaffold with a NavHost as its content. NavHost host 2 screens. One screen contains the bottomNavigationBar and another screen doesnot.

How can I display create a snack bar that can be used globally which is displayed at the bottom of the screen if no bottomNavigationView is there but adds a bottom padding of height = bottomNavigationHeight if the screen contains bottomNavigationView?

Below is my main content:


@Composable
fun MainScreen() {
    val navController = rememberNavController()
    val scaffoldState = rememberScaffoldState()
    Scaffold(
        scaffoldState = scaffoldState
    ) {
        NavHost(navController = navController, "first") {
            composable("first") {
                FirstScreen()
            }
            composable("second") {
                SecondScreen()
            }
        }

    }
}

My first screen.

// No bottom navigation
@Composable
fun FirstScreen() {
    Text("Hello World")
}

My second screen:

// Contains bottom nav
@Composable
fun SecondScreen() {
    Scaffold(bottomBar = { MyBottomBar() }) {

    }
}

Now, I can use CompositionLocal to send snackBarHostState from scaffold state to all my screens. But, I want first screen to display the snack bar without bottom padding and second screen to display the snack bar with padding for the bottomNavView.

How can I achieve the dynamic position of snackBar??

P.S. This is a simplified version of my issue. I have about 6-7 screen for my MainContent and many screens for the screen with bottom nav.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

能否归途做我良人 2025-02-13 10:15:31

我认为您可以遵循本文:

首先,您可以创建一个 defaultsnackbar composable composable:

import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.material.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

@Composable
fun DefaultSnackbar(
    snackbarHostState: SnackbarHostState,
    modifier: Modifier = Modifier,
    onDismiss: () -> Unit = { }
) {
    SnackbarHost(
        hostState = snackbarHostState,
        snackbar = { data ->
            Snackbar(
                modifier = Modifier.padding(16.dp),
                content = {
                    Text(
                        text = data.message,
                        style = MaterialTheme.typography.body2
                    )
                },
                action = {
                    data.actionLabel?.let { actionLabel ->
                        TextButton(onClick = onDismiss) {
                            Text(
                                text = actionLabel,
                                color= MaterialTheme.colors.primary,
                                style = MaterialTheme.typography.body2
                            )
                        }
                    }
                }
            )
        },
        modifier = modifier
            .fillMaxWidth()
            .wrapContentHeight(Alignment.Bottom)
    )
}

然后处理<<<代码> firstScreen secondscreen 之类的snackbarhoststate 都这样:

    val scaffoldState = rememberScaffoldState()

    Scaffold(
        scaffoldState = scaffoldState,
        snackbarHost = { scaffoldState.snackbarHostState }
    ) {
        Column(
            modifier = Modifier
                .fillMaxSize()
                .padding(scaffoldPadding)
        ) {
            Box(modifier = Modifier.weight(1f)) {
                // Content of the screen
                DefaultSnackbar(
                    snackbarHostState = scaffoldState.snackbarHostState,
                    modifier = Modifier.align(Alignment.BottomCenter)
                ) {
                    scaffoldState.snackbarHostState.currentSnackbarData?.dismiss()
                }
            }
            // The bottom bar if have
        }
    }

I think you can follow this article: https://www.devbitsandbytes.com/configuring-snackbar-jetpack-compose-using-scaffold-with-bottom-navigation/

First you can create a DefaultSnackbar composable:

import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.material.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

@Composable
fun DefaultSnackbar(
    snackbarHostState: SnackbarHostState,
    modifier: Modifier = Modifier,
    onDismiss: () -> Unit = { }
) {
    SnackbarHost(
        hostState = snackbarHostState,
        snackbar = { data ->
            Snackbar(
                modifier = Modifier.padding(16.dp),
                content = {
                    Text(
                        text = data.message,
                        style = MaterialTheme.typography.body2
                    )
                },
                action = {
                    data.actionLabel?.let { actionLabel ->
                        TextButton(onClick = onDismiss) {
                            Text(
                                text = actionLabel,
                                color= MaterialTheme.colors.primary,
                                style = MaterialTheme.typography.body2
                            )
                        }
                    }
                }
            )
        },
        modifier = modifier
            .fillMaxWidth()
            .wrapContentHeight(Alignment.Bottom)
    )
}

Then handle the SnackbarHostState in both FirstScreen and SecondScreen like that:

    val scaffoldState = rememberScaffoldState()

    Scaffold(
        scaffoldState = scaffoldState,
        snackbarHost = { scaffoldState.snackbarHostState }
    ) {
        Column(
            modifier = Modifier
                .fillMaxSize()
                .padding(scaffoldPadding)
        ) {
            Box(modifier = Modifier.weight(1f)) {
                // Content of the screen
                DefaultSnackbar(
                    snackbarHostState = scaffoldState.snackbarHostState,
                    modifier = Modifier.align(Alignment.BottomCenter)
                ) {
                    scaffoldState.snackbarHostState.currentSnackbarData?.dismiss()
                }
            }
            // The bottom bar if have
        }
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文