一、前言
学习课程时,对于自己不懂的点的记录。
对于cy老师第二节课总结。
二、内容
1、PPT介绍scaffold
2、开始代码实操
先新建一个screen包,写一个Homescreen函数,包括四个页面。
再新建一个compenent包,写一个displayText函数,是对四个页面容器的统一封装。里面是一个Box容器修饰。再回到Homescreen中传入不同参数以示区别。
在screen包中,创建一个Screen的类来管理这些界面。可继承的,这个类参数不仅要有route,title,icon 还要有一个加载页面函数 @Composable ()->unit 。在这个类里面实现界面的数据对象,最后将这些对象存在screens列表中。
在screen包中,创建一个Mainscreen函数,写脚手架。要传入当前页面可以用currentScreen变量来记录到内存,并注意变量是MutableState<Screen>
好。按照这样写,从topAppBar开始写,最后content大括号部分Box容器可以用currentScreen.value.loadScreen.invoke()展示页面主体及上面效果。
topAppbar部分的action里继续写下拉菜单。先设置一个变量expanded表示下来与否,写一个Button里面是DropDownMenu。这一部分用screens.forEach来设置,并在最后加一个退出图标。最后将这繁琐一大部分放到Compenent包里创建MenuViews。
再写Bottombar导航NavigationBarItem部分,也是screens.forEach 选中页面,点击切换。同样剪切到Compenent的BottomViews里。
然后写悬浮按钮。FloatingActionButton。点击就将currentScreen切换到HomeScreen,这里面还有一些设计样式的布局。
最后写侧拉页面,在component包里新建一个DrawViews函数。drawContent分为DrawerHead和DrawerBottom。DrawerHead细致写:
val (imgRef,titleRef,contentRef) = remember{createRefs()}
createVerticalChain(titleRef,contentRef, chainStyle = ChainStyle.Spread)
没听清这两个约束布局效果。设置水平竖直引导线控制位置。写了三个部分。
DrawerBottom写导航。Screen.forEach后,NavigationBarItem有图标标签,选中就跳转,还可以颜色修饰。主页面的跳转也可以改成
DrawViews(drawerState,currentScreen)
最后将DrawViews和MainScreen结合。记录一个状态变量,但无法直接设置值,需要在协程中打开运行。在DrawViews退出操作也同样是协程。
OK!写完!!后面还有一些对于代码优化方面内容。
优化一:将状态封装定义一个类StateHolder,实现一个rememberState函数。定义一个容器,四个状态就是类里面属性。实现一个组合函数,将状态默认值保存至内存中,需要时再提取出来,再用这四个值创建四个对象。
// val currentScreen:MutableState<Screen> =remember{ mutableStateOf(Screen.HomePage) }
// val expanded = remember { mutableStateOf(false) }
// val drawerState = rememberDrawerState(DrawerValue.Closed)
// val scope= rememberCoroutineScope()
val stateHolder= rememberState()
改成
//将状态保存在状态容器中
class stateHolder(val drawerState: DrawerState,val currentScreen: MutableState<Screen>,
val expanded:MutableState<Boolean>,val scope: CoroutineScope) {
}
@Composable
fun rememberState(drawerState: DrawerState= rememberDrawerState(initialValue = DrawerValue.Closed),
currentScreen: MutableState<Screen> = remember { mutableStateOf(Screen.HomePage) },
expanded:MutableState<Boolean> = remember { mutableStateOf(false) },
scope: CoroutineScope= rememberCoroutineScope()):stateHolder
= remember(drawerState,currentScreen,expanded,scope) { //
stateHolder(drawerState,currentScreen,expanded,scope)
}
优化二:利用导航。(自己先同步和定义和库依赖)
定义MainScreen2。不需要界面,只需要route,icon,title。加载页面也是我们自己操作。定义导航图,导航数组,控件(数组的)。传递参数route。继续写NavigationBarItem一样的选中调换。区别:不用记录当前状态,只需route就可跳转。
cpp
@Composable
fun NavigationGraphScreen(navController: NavHostController){
//顶层的导航控件一定要是数组的 否则后面会出错
NavHost(navController = navController, startDestination = "home") {
composable(route = "home") {
HomeScreen()
}
composable(route = "config") {
ConfigScreen()
}
composable(route = "help") {
HelpScreen()
}
}
}
@Preview
@Composable
fun MainScreen2() {
val navController: NavHostController = rememberNavController()
Scaffold(bottomBar = {
BottomAppBar {
screens.forEach{
NavigationBarItem(
selected =navController.currentDestination?.route==it.route ,
onClick = {
navController.navigate(it.route)
},
icon = {
Icon(it.icon, contentDescription = "null")
}
)
}
}
}) {
Box (modifier = Modifier.padding(it)){
NavigationGraphScreen(navController)
}
细节:将页面压栈 的清栈操作需要考虑。
现在放上源代码:
【超级会员V1】通过百度网盘分享的文件:navigati...
链接:https://pan.baidu.com/s/1xetKh4LJ9SMQRA2gMUi43g?pwd=rx2c
提取码:rx2c
复制这段内容打开「百度网盘APP 即可获取」