如何在Jetpack Compose中设置Snackbar的动态位置?

3

我有一个Scaffold,其内容为NavHost。NavHost包含两个屏幕。一个屏幕包含bottomNavigationBar,另一个屏幕则没有。

我该如何创建一个全局可用的snackBar,如果没有bottomNavigationView,则显示在屏幕底部,但如果屏幕包含bottomNavigationView,则添加高度为bottomNavigationHeight的底部填充?

下面是我的主要内容:


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

我的第二个屏幕:

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

    }
}

现在,我可以使用CompositionLocal将snackBarHostState从scaffold状态发送到所有屏幕。但是,我希望第一个屏幕显示没有底部填充的snack bar,第二个屏幕显示具有底部导航视图填充的snack bar。
如何实现snackBar的动态位置?
注:这是我问题的简化版本。我的MainContent有大约6-7个屏幕,屏幕底部有许多屏幕。

你尝试过应用偏移修饰符吗? - realh
1个回答

0

我觉得你可以按照这篇文章操作:https://www.devbitsandbytes.com/configuring-snackbar-jetpack-compose-using-scaffold-with-bottom-navigation/

首先,你可以创建一个 DefaultSnackbar 组合:

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

然后在FirstScreenSecondScreen中都处理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
        }
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接