Jetpack Compose之隐藏Scaffold的BottomNavigation
做主页导航时会用到底部导航栏,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的更多相关文章
- Jetpack Compose学习(7)——MD样式架构组件Scaffold及导航底部菜单
Jetpack Compose学习(7)--MD样式架构组件Scaffold及导航底部菜单 | Stars-One的杂货小窝 Compose给我们提供了一个Material Design样式的首页组件 ...
- Jetpack Compose What and Why, 6个问题
Jetpack Compose What and Why, 6个问题 1.这个技术出现的背景, 初衷, 要达到什么样的目标或是要解决什么样的问题. Jetpack Compose是什么? 它是一个声明 ...
- Jetpack Compose学习(3)——图标(Icon) 按钮(Button) 输入框(TextField) 的使用
原文地址: Jetpack Compose学习(3)--图标(Icon) 按钮(Button) 输入框(TextField) 的使用 | Stars-One的杂货小窝 本篇分别对常用的组件:图标(Ic ...
- Jetpack Compose学习(5)——从登录页美化开始学习布局组件使用
原文:Jetpack Compose学习(5)--从登录页美化开始学习布局组件使用 | Stars-One的杂货小窝 本篇主要讲解常用的布局,会与原生Android的布局控件进行对比说明,请确保了解A ...
- Jetpack Compose学习(6)——关于Modifier的妙用
原文: Jetpack Compose学习(6)--关于Modifier的妙用 | Stars-One的杂货小窝 之前学习记录中也是陆陆续续地将常用的Modifier的方法穿插进去了,本期就来详细的讲 ...
- Jetpack Compose和View的互操作性
Jetpack Compose Interoperability Compose风这么大, 对于已有项目使用新技术, 难免会担心兼容性. 对于Compose来说, 至少和View的结合是无缝的. (目 ...
- Jetpack Compose学习(1)——从登录页开始入门
原文地址:Jetpack Compose学习(1)--从登录页开始入门 | Stars-One的杂货小窝 Jetpack Compose UI在前几天出了1.0正式版,之前一直还在观望,终于是出了正式 ...
- Jetpack Compose 1.0 终于要投入使用了!
前言 Jetpack Compose 是用于构建原生界面的「新款 Android 工具包」.2021 Google IO 大会上,Google宣布:「Jetpack Compose 1.0 即将面世」 ...
- Android Kotlin Jetpack Compose UI框架 完全解析
前言 Q1的时候公司列了个培训计划,部分人作为讲师要上报培训课题.那时候刚从好几个Android项目里抽离出来,正好看到Jetpack发布了新玩意儿--Compose,我被它的快速实时打包给吸引住了, ...
随机推荐
- sqlite无法保存数据
springboot使用连接sqlite数据,使用jdbc:sqlite::resource:db/XXX.db方式连接数据库为只读,使用绝对路径才可以写入.
- 基于Redisson实现分布式锁源码解读
文章目录 一.分布式锁的概念 和 使用场景 二.将redis官网对于分布式锁(红锁)的定义和Redisson实现做概括性总结 三.基于Redisson的分布式实现方案 四.加锁过程分析 五.锁重入过程 ...
- atom之插件安装及相关
1. simplified-chinese-menu 汉化软件 2. file-icons 加上文件图标 3. language-vue 加上vue语言支持 4. platformio-ide-ter ...
- 浅谈Java类中的变量初始化顺序
一.变量与构造器的初始化顺序 我们知道一个类中具有类变量.类方法和构造器(方法中的局部变量不讨论,他们是在方法调用时才被初始化),当我们初始化创建一个类对象时,其初始化的顺序为:先初始化类变量,再执行 ...
- Java8 Lambda表达式(一)
目录 一.应用场景引入 优化一:使用策略模式 优化二:使用匿名内部类 优化三:使用Lambda表达式 优化四:使用Stream API 二.Lambda运算符和对应语法 语法格式 Lambda表达式需 ...
- Windows API 进程相关笔记
0. 前言 最近做了一个进程信息相关的项目,整理了一下自己做项目时的笔记,分享给大家 1. 相关概念 1.1 HANDLE 概念 HANDLE(句柄)是Windows操作系统中的一个概念. 在Wind ...
- java基础技术集合面试【笔记】
java基础技术集合面试[笔记] Hashmap: 基于哈希表的 Map 接口的实现,此实现提供所有可选的映射操作,并允许使用 null 值和 null 键(除了不同步和允许使用 null 之外,Ha ...
- 精简ABP的模块依赖
ABP的模块非常方便我们扩展自己的或使用ABP提供的模块功能,对于ABP自身提供的模块间的依赖关系想一探究竟,并且试着把不必要的模块拆掉,找到那部分核心模块.本次使用的是AspNetBoilerpla ...
- 3 分钟了解 JSON Schema
大家好,我不是鱼皮. 幸运又不幸,我是一名程序员,他也是一名程序员. 周末,我在开发网站,他在开发游戏,两个人一起写代码,一起写 Bug 头秃,竟也有了一丝别样的浪漫,好不自在! 今天,他遇到了一个后 ...
- SQL 练习11
查询至少有一门课与学号为" 01 "的同学所学相同的同学的信息 SELECT * from Student WHERE SId in (SELECT SId from sc WHE ...