做主页导航时会用到底部导航栏,Jetpack Compose提供了基础槽位的布局Scaffold,使用Scaffold可以构建底部导航栏,例如:

@Composable
fun Greeting(vm: VM) {
val list = listOf("One", "Two", "Three")
var selectedItem = remember {
mutableStateOf(0)
}
val navController = rememberNavController() Scaffold(bottomBar = {
state.takeIf { it.value }?.let {
BottomNavigation {
list.forEachIndexed { index, label ->
BottomNavigationItem(
label = { Text(text = label) },
selected = index == selectedItem.value,
onClick = { selectedItem.value = index },
icon = {
Icon(
painter = painterResource(id = R.drawable.ic_launcher_foreground),
contentDescription = null
)
})
}
}
}
}) {
NavHost(navController = navController, startDestination = "one") {
composable(route = "one") { PageList(navController, vm) }
composable(route = "detail") { PageDetail(vm) }
}
}
}

这是一个最简单的Scaffold,其主页时PageList,显示一列数字,点击数字后会跳转到PageDetail页面。

但是有个很大的问题,就是在跳转到PageDetail页面之后,BottomNavigation并没有随之消失,于是乎出现了这样一个奇怪的现象:

为了解决这个问题,可以采用State去控制BottomNavigation的可见性,并将其保存在ViewModel中。

具体做法是:

1.在ViewModel中创建一个包含Boolean值的LiveData变量state。当state为true时绘制BottomNavigation,为false时不绘制

2.在包含Scaffold页面中监听state,并控制BottomNavigation的可见性。

3.在PageList(也就是Scaffold导航的主页)进入时设置state为true、退出时设置state为false

// ViewModel
class VM: ViewModel() {
private val _state: MutableLiveData<Boolean> = MutableLiveData(true)
val state: LiveData<Boolean> get() = _state
fun setState(status: Boolean) {
_state.postValue(status)
}
} // MainPage
@Compose MainPage(vm: VM) {
LaunchedEffect(key1 = true) {
vm.setState(true)
} DisposableEffect(key1 = true) {
onDispose {
vm.setState(false)
}
}
} // page contains Scaffold
@Composable
fun Greeting(vm: VM) {
// State of BottomNavigation`s visibility
val state = remember { mutableStateOf<Boolean>(true) }
// read the BottomNavigation`s visibility from ViewModel and send to State
vm.state.observeAsState().value?.let { state.value = it } Scaffold(bottomBar = {
// show / hide BottomNavigation controlled by State
state.takeIf { it.value }?.let {
BottomNavigation {
list.forEachIndexed { index, label ->
BottomNavigationItem(
label = { Text(text = label) },
selected = index == selectedItem.value,
onClick = { selectedItem.value = index },
icon = {
Icon(
painter = painterResource(id = R.drawable.ic_launcher_foreground),
contentDescription = null
)
})
}
}
}
}) {
NavHost(navController = navController, startDestination = "one") {
composable(route = "one") { PageList(navController, vm) }
composable(route = "detail") { PageDetail(vm) }
}
}
}

这种做法的好处是简单,侵入性低,无需修改系统api也无需自定义view。缺点就是麻烦,需要在导航中的每个主页都进行设置。


我在StackOverflow上提问时有人回答了另一个办法。这个办法是给每个屏幕添加标志位,来区分是否是导航的主页,之后再创建BottomNavigation时进行判断。贴一下:

You need to specify which screens you want to show and which screens you dont want; Otherwise it will show to all the screens inside Scaffold's body (which you have bottomBar). The code below was from my app.

Create a state which observes any destination changes on the navController

Inside when you can put any screens that you want to show navigationBar else just set currentScreen to NoBottomBar

@Composable
private fun NavController.currentScreen(): State<MainSubScreen> {
val currentScreen = remember { mutableStateOf<MainSubScreen>(MainSubScreen.Home) } DisposableEffect(key1 = this) {
val listener = NavController.OnDestinationChangedListener { _, destination, _ ->
when {
destination.hierarchy.any { it.route == MainSubScreen.Home.route } -> {
currentScreen.value = MainSubScreen.Home
} else -> currentScreen.value = MainSubScreen.NoBottomBar
}
}
addOnDestinationChangedListener(listener)
}
return currentScreen
}

On the Scaffold where you put ur bottomBar

so you can check if currentScreen was NoBottomBar if it was, don't show it

// initialized currentScreeen above
val currentScreen by navController.currentScreen()
Scaffold(
bottomBar = {
if (currentScreen != MainSubScreen.NoBottomBar) {
MainBottomNavigation()
} else Unit
}
) {
// Your screen
}

Jetpack Compose之隐藏Scaffold的BottomNavigation的更多相关文章

  1. Jetpack Compose学习(7)——MD样式架构组件Scaffold及导航底部菜单

    Jetpack Compose学习(7)--MD样式架构组件Scaffold及导航底部菜单 | Stars-One的杂货小窝 Compose给我们提供了一个Material Design样式的首页组件 ...

  2. Jetpack Compose What and Why, 6个问题

    Jetpack Compose What and Why, 6个问题 1.这个技术出现的背景, 初衷, 要达到什么样的目标或是要解决什么样的问题. Jetpack Compose是什么? 它是一个声明 ...

  3. Jetpack Compose学习(3)——图标(Icon) 按钮(Button) 输入框(TextField) 的使用

    原文地址: Jetpack Compose学习(3)--图标(Icon) 按钮(Button) 输入框(TextField) 的使用 | Stars-One的杂货小窝 本篇分别对常用的组件:图标(Ic ...

  4. Jetpack Compose学习(5)——从登录页美化开始学习布局组件使用

    原文:Jetpack Compose学习(5)--从登录页美化开始学习布局组件使用 | Stars-One的杂货小窝 本篇主要讲解常用的布局,会与原生Android的布局控件进行对比说明,请确保了解A ...

  5. Jetpack Compose学习(6)——关于Modifier的妙用

    原文: Jetpack Compose学习(6)--关于Modifier的妙用 | Stars-One的杂货小窝 之前学习记录中也是陆陆续续地将常用的Modifier的方法穿插进去了,本期就来详细的讲 ...

  6. Jetpack Compose和View的互操作性

    Jetpack Compose Interoperability Compose风这么大, 对于已有项目使用新技术, 难免会担心兼容性. 对于Compose来说, 至少和View的结合是无缝的. (目 ...

  7. Jetpack Compose学习(1)——从登录页开始入门

    原文地址:Jetpack Compose学习(1)--从登录页开始入门 | Stars-One的杂货小窝 Jetpack Compose UI在前几天出了1.0正式版,之前一直还在观望,终于是出了正式 ...

  8. Jetpack Compose 1.0 终于要投入使用了!

    前言 Jetpack Compose 是用于构建原生界面的「新款 Android 工具包」.2021 Google IO 大会上,Google宣布:「Jetpack Compose 1.0 即将面世」 ...

  9. Android Kotlin Jetpack Compose UI框架 完全解析

    前言 Q1的时候公司列了个培训计划,部分人作为讲师要上报培训课题.那时候刚从好几个Android项目里抽离出来,正好看到Jetpack发布了新玩意儿--Compose,我被它的快速实时打包给吸引住了, ...

随机推荐

  1. js中的 true 与 false

    可判断为 false 的情况: 0,-0,NaN,undedined,"",false,null,缺省的值 可判断为 true 的情况: 除false的其他情况均可,包括负数.&q ...

  2. 微信小程序工具下载与安装

    下载 第一步:百度搜索"微信公众平台" 第二步:登录微信公众平台 第三步:点击微信开发者工具 第四步:按照自己的操作系统下载对应的版本的开发者工具,我的是Windows10 64位 ...

  3. (opencv01)读入图像

    (opencv01)Opencv之读入图像 读入图像  img = cv2.imread(filepath, flags) filepath : 要读入图片的完整路径 flags : 读入图片的标志 ...

  4. php cookie赋值使用

    setcookie('username',$user,time()+3600*24);    //cookie赋值 public function login(){ //cookie 使用       ...

  5. Calcite(一):javacc语法框架及使用

    是一个动态数据管理框架. 它包含许多组成典型数据库管理系统的部分,但省略了存储原语.它提供了行业标准的SQL解析器和验证器,具有可插入规则和成本函数的可自定义优化器,逻辑和物理代数运算符,从SQL到代 ...

  6. 计算机网络模型和5G知识

    目录 一.网络布线及信号传输 1.信号 2.传输介质 2.1双绞线 2.2光纤 2.3常见性问题 三.无线传播介质 四.综合布线系统 五.计算机的数制度以及运算 一.网络布线及信号传输 1.信号 频率 ...

  7. [源码解析] 机器学习参数服务器 Paracel (1)-----总体架构

    [源码解析] 机器学习参数服务器 Paracel (1)-----总体架构 目录 [源码解析] 机器学习参数服务器 Paracel (1)-----总体架构 0x00 摘要 0x01使用 1.1 配置 ...

  8. Java面向对象14——接口

    接口  package oop.demon01.demon09; ​ //抽象思维~Java ​ //interface 定义的关键字 , 接口都需要有实现类 public interface Use ...

  9. UE4点选源码分析

    在UE插件开发中,时常会用到场景预览窗口的功能,也经常会有点选场景里的物体而同步改变工具界面的需求,网上教程多为讲解如何打开一个预览界面.在最近的一次需求开发中,我粗读了关卡编辑器和蓝图编辑器的Vie ...

  10. Java知识复习回顾

    1.MVC 三层架构: M:Model 数据模型层 V:View 视图层 C:Controller控制器层 目的:解耦 2.Spring Spring:轻量级的Java开源框架,容器,目的是解决企业级 ...