Jetpack Compose 中底部导航栏重叠屏幕内容

85

我有一个BottomNavBar,它被调用在ScaffoldbottomBar中。
每个屏幕都包含一个LazyColumn,其中显示了一堆图片。
出于某种原因,当我完成滚动后,BottomNavBar 重叠在项目列表的下部分。
我该怎么修复这个问题?

输入图像描述

这里是MainActivity的设置内容

SetContent{
    Scaffold(
        topBar = {
            TopAppBar(
                title = { Text(text = "tartufozon") },
                actions = {
                    IconButton(onClick = { Timber.d("Mail clicked") }) {
                        Icon(Icons.Default.Email, contentDescription = null)
                    }
                }
            )
        },
        bottomBar = {
            BottomNavBar(navController = navController)
        }
    ) {
    BottomNavScreensController(navController = navController)
    }
}
6个回答

162
根据 Scaffold 的 API 定义,你的内部内容(即包含 BottomNavScreensController 的尾随 lambda 表达式)会被赋予一个 PaddingValues 对象,用于为顶部应用栏、底部导航栏等提供正确的填充量。

目前你没有引用该填充量,因此你的内容未进行填充。这就是导致重叠的原因。

你可以在 BottomNavScreensController 周围添加一个 Box 来应用填充,或者直接将填充传递给 BottomNavScreensController,以使每个单独的屏幕都能正确应用填充。这两种解决方案都可以。

Scaffold(
    topBar = {
      //
    },
    bottomBar = {
        //
    }
    ) { innerPadding ->
        // Apply the padding globally to the whole BottomNavScreensController
        Box(modifier = Modifier.padding(innerPadding)) {
            BottomNavScreensController(navController = navController)
        }
    }
}

使用lazyColumn和视图系统时,内部填充应手动计算吗? - mrzbn
考虑当底部导航栏与形状相遮挡时,被裁剪的底部导航栏区域将使用脚手架的背景颜色。我的意思是,在设置内容背景颜色之后应用内边距。请参考此链接:https://stackoverflow.com/questions/76914671/jetpack-compose-bottombar-transparent-background-color-when-it-has-rounded-corne - mrzbn

12

根据ianhanniballake的回答和评论,为了节省您的时间,代码应该是这样的:

Scaffold(
    topBar = {
      //
    },
    bottomBar = {
        //
    }
    ) { innerPadding ->
        Box(modifier = Modifier.padding(
          PaddingValues(bottom = innerPadding.calculateBottomPadding()) {
            BottomNavScreensController(navController = navController)
        }
    }
}

您可以使用 Modifier.padding(bottom=...),而不是指定0。 - Lukas
你说得对。回答已更新。谢谢。 - RobertoAllende

7

您不再需要进行任何计算。在搭建内容中,执行以下操作:

content = { padding ->
  Column(
    modifier = Modifier.padding(padding)
  ) {...

6
Scaffold(
    bottomBar = {
       BottomNavigationBar(navController = navController)
   }
) { innerPadding ->
      Box(modifier = Modifier.padding(innerPadding)) {
               DestinationsNavHost(
                  navGraph = NavGraphs.root,
                  navController = navController,
                  engine = navHostEngine
                )
         }
}

1

在内容中添加您的布局和视图,带有其填充,就像示例中所示:

Scaffold(
        content = {
            Box(modifier = Modifier.padding(it)) {
                //add your layout here
            }

        },
        topBar = { 
                 //your top bar
        },
        floatingActionButton = {
           //your floating action bar
        },
        bottomBar = {
            //your bottom navigation
        }
    )

-1

根据ianhanniballake的回答,如果您在主屏幕上有一个列表,并希望显示/隐藏底部栏。当您返回到列表屏幕时(滚动状态位于底部),并显示导航栏时,它将执行意外行为。列表项将向上滚动一点,导致列表无法完全滚动到底部。

这是因为当您返回到列表屏幕并想要显示底部栏时,列表已经存在。然后底部栏将显示,列表将不再计算更多的innerPadding。

enter image description here

为了处理这个问题,只需像这样将 innerPadding 传递到列表屏幕中:
            Scaffold(
                bottomBar = {
                BottomNavBar(navController)
            }) { innerPadding ->
            NavHost(
                navController = navController,
                startDestination = MovieListDirections.destination
            ) {
                MovieListDirections.screenWithPaddingBottomBar(
                    this,
                    innerPadding.calculateBottomPadding() // pass here
                )
            }

然后在列表屏幕中

@Composable
fun MovieListMainView(viewModel: MovieListViewModel = hiltViewModel(),
                  bottomBarHeight: Float) {
    val movieList by viewModel.movieList.collectAsState()
    var navBarHeight by rememberSaveable { mutableStateOf(0f) }

    if (bottomBarHeight != 0f) {
        navBarHeight = bottomBarHeight
    }

    MovieListLayout().MovieGridLayout(
        modifier = Modifier.padding(0.dp, 0.dp, 0.dp, navBarHeight.dp),
        movies = movieList.movieList.movieItems,
        onItemClick = {
            viewModel.onMovieClicked(it)
        })
}

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