remember 方法
开始之前先介绍一下 remember 方法。
因为(重组) Composable 函数可以被执行多次,函数中声明变量的赋值语句每次都会被执行,这使得变量每次都会被赋值初始值或者新的对象。 remember 方法可以解决这个问题。
remember 方法两种使用形式 :
- remember(calculation:@DisallowComposableCalls () -> T): 没有 key , 每返回的都是第一次执行 calculation 返回的结果
- remember(vararg keys:Any?,calculation:@DisallowComposableCalls () -> T): 当 key 改变时会执行 calculation 返回结果,不变时返回上一次 calculation 返回结果
val b = remember { mutableStateOf(0) } 每次运行这行代码返回的都是第一次创建的 MutableState 对象。
三种使用 remember 声明 MutableState 的方式:
- val mutableState = remember { mutableStateOf(default) } // 返回 MutableState
- var value by remember { mutableStateOf(default) } // 返回 T
- val (value, setValue) = remember { mutableStateOf(default) } // 利用 kotlin 语法 将 MutableState 解构赋值给 value 和 setValue
rememberSaveable 在 remember 功能的基础上还支持 Activity 进程意外销毁后重建的情况(例如配置变更) 下的保存。
可以保存 Bundle 或带有 @Parcelize 注解的对象,还可以自定义 Saver 来自定义保存/恢复规则
搭建首页
除了基本布局以外,Compose 还提供了一些槽位组件,顾名思义就是已经把布局写好,只要在指定的位置插入想要的内容。使用这些组件需要引入 Material 依赖。
Material 3 已经上线,依赖和使用方法与原来的 Material 有所不同。这两个依赖引用一个就够了,在创建项目的时我们已经添加好了 Material 3 依赖。
完整的 Material 3 介绍参见 官网 。
首页效果如下:
- Scaffold 最常用的布局容器,提供了顶部标题栏,底部导航栏、浮动按钮、snackbar、内容 5个槽位。
- CenterAlignedTopAppBar 标题居中的顶部标题栏(泪目了)
- NavigationBar + NavigationBarItem :最多 5 个 Item 的底部导航栏
在每个 ui 模块中创建模块首页文件 提供一个占位的 composable 方法后将其添加到 app 依赖中。
@Composable
fun UiHome(){
Text(text = "Home")
}
在 app 模块 ui 包下创建 WanApp.kt , 添加枚举类封装底部导航按钮信息
enum class BottomBarItem(
val label: String,
val icon: @Composable () -> Unit,
) {
Home(
"首页",
{ Icon(imageVector = Icons.Filled.Home, contentDescription = "") },
),
// ...... 问答 、项目 、广场 、体系
}
添加 TopBar 方法用于 Scaffold 的 topBar 槽位
@Composable
internal fun TopBar(title: String, onProfileClick: () -> Unit) {//标题,左侧导航按钮点击事件
CenterAlignedTopAppBar(
title ={ Text( text = title)},
navigationIcon = {
IconButton(onClick = onProfileClick) {
Icon(imageVector = Icons.Filled.Person, contentDescription = "")
}
}
)
}
添加 BottomBar 方法用于 Scaffold 的 bottomBar 槽位
@Composable
internal fun BottomBar(
items:Array<BottomBarItem>, //item 集合
selectedIndex:Int = 0, // 当前选中 item 的索引
onBottomItemClick:(Int) -> Unit) // item 点击事件
{
NavigationBar {
items.forEachIndexed { index, bottomBarItem ->
NavigationBarItem(
icon = bottomBarItem.icon,
selected = index == selectedIndex,
onClick = {onBottomItemClick(index)},
colors = NavigationBarItemDefaults.colors()// 设置颜色
)
}
}
}
添加 WanApp 方法收拢 Compose 代码,在方法中用 Scaffold 创建首页
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun WanApp(){
//当前选中的 BottomBarItem 索引
//Scaffold 根据选中的状态显示不同的内容
var selectedItemIndex by remember { mutableStateOf(0) }
val bottomBarItems = remember { BottomBarItem.values() }
WanAndroidTheme {
// A surface container using the 'background' color from the theme
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
Scaffold(
topBar = {
TopBar(title = bottomBarItems[selectedItemIndex].label) {
//todo 跳转到我的页面
}
},
bottomBar = {
BottomBar(bottomBarItems, selectedItemIndex) {
//点击底部 item 时更新 selectedItemIndex
selectedItemIndex = it
}
},
containerColor = Color.LightGray
) {
Box(modifier = Modifier
.padding(it)
.fillMaxSize()){
//根据 selectedItemIndex 在 content 中显示不同的页面
when(selectedItemIndex){
0 -> UiHome()
1 -> UiFqa()
2 -> UiProfile()
3 -> UiSquare()
else -> UiSystem()
}
}
}
}
}
}
收拢后 Main Activity 中的代码
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
WanApp()
}
}
}
简单实现了首页功能,主要目的是熟悉 Compose 中 Composable 方法,状态, rememeber 方法,及 Material 3 中的槽位组件的使用。 接下来要使用 Jectpack Navigation 完成真正的首页功能。