Jetpack Compose学习(7)——MD样式架构组件Scaffold及导航底部菜单
Jetpack Compose学习(7)——MD样式架构组件Scaffold及导航底部菜单 | Stars-One的杂货小窝
Compose给我们提供了一个Material Design样式的首页组件(Scaffold),我们可以直接套用从而完成一个APP的首页界面
本系列以往文章请查看此分类链接Jetpack compose学习
由于Scaffold中还包含有其他的组件,所以讲解Scaffold先讲解前置的一些组件
TopAppBar
首先,便是TopAppBar,其本质就是我们Android原生常见的Toolbar,不过其封装的比较好,可以快速构建,下面是其的参数列表
TopAppBar(
title: @Composable () -> Unit,
modifier: Modifier = Modifier,
navigationIcon: @Composable (() -> Unit)? = null,
actions: @Composable RowScope.() -> Unit = {},
backgroundColor: Color = MaterialTheme.colors.primarySurface,
contentColor: Color = contentColorFor(backgroundColor),
elevation: Dp = AppBarDefaults.TopAppBarElevation
)
title标题,接收Compose组件,可以传个Text文本进去modifier修饰符,详情见上一章节navigationIcon导航图标actions动作组件backgroundColor背景色contentColor内容颜色elevation阴影
可能说的那么明确,我们直接上代码和效果图,各位就清晰了
TopAppBar(
navigationIcon = {
IconButton(
onClick = {}
) {
Icon(Icons.Filled.Menu, null)
}
},
title = {
Text("stars-one的测试应用")
},actions = {
IconButton(
onClick = {}
) {
Icon(Icons.Filled.Share, null)
}
IconButton(
onClick = {}
) {
Icon(Icons.Filled.Settings, null)
}
}
)
效果图如下

FloatingActionButton
比较常见的悬浮按钮,一般里面是个简单的按钮,参数与之前的Button一样,详情请参考Jetpack Compose学习(3)——图标(Icon) 按钮(Button) 输入框(TextField) 的使用 | Stars-One的杂货小窝
FloatingActionButton(
onClick: () -> Unit,
modifier: Modifier = Modifier,
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
shape: Shape = MaterialTheme.shapes.small.copy(CornerSize(percent = 50)),
backgroundColor: Color = MaterialTheme.colors.secondary,
contentColor: Color = contentColorFor(backgroundColor),
elevation: FloatingActionButtonElevation = FloatingActionButtonDefaults.elevation(),
content: @Composable () -> Unit
)
使用:
FloatingActionButton(onClick = { /*TODO*/ }) {
Icon(imageVector = Icons.Default.Add, contentDescription = null)
}

PS: 一般这个与
Scaffold连用,Scaffold里面可控制FloatingActionButton的位置
除此之外,还有个ExtendedFloatingActionButton,这种就是可以带图标和文字的,如下图
ExtendedFloatingActionButton(
icon = { Icon(Icons.Filled.Favorite, contentDescription = null) },
text = { Text("ADD TO BASKET") },
onClick = { /*do something*/ }
)
ExtendedFloatingActionButton和FloatingActionButton区别是,ExtendedFloatingActionButton是以文字为主,图标是可选的,而FloatingActionButton只显示图标

BottomAppBar
这个与之前的TopAppBar参数有所不同,从名字看我们知道其实放在底部的一个Toolbar,但是其本身是不带有位置控制,也是得与Scaffold连用,如果单独使用,效果也是会和TopAppBar的一样放在页面的顶头
BottomAppBar(
modifier: Modifier = Modifier,
backgroundColor: Color = MaterialTheme.colors.primarySurface,
contentColor: Color = contentColorFor(backgroundColor),
cutoutShape: Shape? = null,
elevation: Dp = AppBarDefaults.BottomAppBarElevation,
contentPadding: PaddingValues = AppBarDefaults.ContentPadding,
content: @Composable RowScope.() -> Unit
)
可以把这个布局看作是个Row布局,里面的参数从名字都能看到出来,设置背景色或者设置padding边距的,这里不再赘述
唯一值得注意的是cutoutShape属性,如果在Scaffold中,有BottomAppBar和FloatingActionButton,可以实现下面的效果

BottomNavigation
BottomNavigation里面会有N个BottomNavigationItem,这里就看你自己准备定义多少个菜单项了
BottomNavigation(
modifier: Modifier = Modifier,
backgroundColor: Color = MaterialTheme.colors.primarySurface,
contentColor: Color = contentColorFor(backgroundColor),
elevation: Dp = BottomNavigationDefaults.Elevation,
content: @Composable RowScope.() -> Unit
)
BottomNavigation提供的一些参数也就是改变颜色或者阴影,重点是在BottomNavigationItem
BottomNavigationItem(
selected: Boolean,
onClick: () -> Unit,
icon: @Composable () -> Unit,
modifier: Modifier = Modifier,
enabled: Boolean = true,
label: @Composable (() -> Unit)? = null,
alwaysShowLabel: Boolean = true,
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
selectedContentColor: Color = LocalContentColor.current,
unselectedContentColor: Color = selectedContentColor.copy(alpha = ContentAlpha.medium)
)
BottomNavigationItem有个selected参数,表示是否选中
icon则是图标的设置,label则是文字,这两个都是需要接收一个组件的
selectedContentColor选中颜色unselectedContentColor未选中颜色
下面直接来个例子讲解
var selectIndex by remember {
mutableStateOf(0)
}
val navList = listOf("首页","发现","我的")
BottomNavigation() {
navList.forEachIndexed { index, str ->
BottomNavigationItem(
selected = index == selectIndex, onClick = { selectIndex = index },
icon = {
Icon(imageVector = Icons.Default.Favorite, contentDescription =null )
},label = {Text(str)}
)
}
}
Text(text = "这是${navList[selectIndex]}")
效果如下所示

Scaffold
Scaffold(
modifier: Modifier = Modifier,
scaffoldState: ScaffoldState = rememberScaffoldState(),
topBar: @Composable () -> Unit = {},
bottomBar: @Composable () -> Unit = {},
snackbarHost: @Composable (SnackbarHostState) -> Unit = { SnackbarHost(it) },
floatingActionButton: @Composable () -> Unit = {},
floatingActionButtonPosition: FabPosition = FabPosition.End,
isFloatingActionButtonDocked: Boolean = false,
drawerContent: @Composable (ColumnScope.() -> Unit)? = null,
drawerGesturesEnabled: Boolean = true,
drawerShape: Shape = MaterialTheme.shapes.large,
drawerElevation: Dp = DrawerDefaults.Elevation,
drawerBackgroundColor: Color = MaterialTheme.colors.surface,
drawerContentColor: Color = contentColorFor(drawerBackgroundColor),
drawerScrimColor: Color = DrawerDefaults.scrimColor,
backgroundColor: Color = MaterialTheme.colors.background,
contentColor: Color = contentColorFor(backgroundColor),
content: @Composable (PaddingValues) -> Unit
)
属性说明
topBar顶部的布局bottomBar底部的布局floatingActionButton悬浮按钮布局floatingActionButtonPosition悬浮按钮位置,有FabPosition.End(默认)和FabPosition.Center可选isFloatingActionButtonDocked与BottomAppBar配合使用,可以实现底部导航条的裁剪效果,效果可以看下图drawerGesturesEnabled是否开启侧边抽屉手势(开启后可侧滑弹出抽屉)drawerShape抽屉的形状drawerContent侧边抽屉内容,是个Column布局,自己可以顺便排列drawerElevation侧边抽屉的阴影drawerBackgroundColor侧边抽屉的背景色drawerContentColor侧边抽屉内容颜色(似乎是覆盖字体颜色而已)drawerScrimColor侧边抽屉遮盖最底层的颜色
基本使用
使用5个属性topBar bottomBar floatingActionButton floatingActionButtonPosition isFloatingActionButtonDocked,实现个简单架构效果
Scaffold(
topBar = {
TopAppBar(
navigationIcon = {
IconButton(
onClick = {}
) {
Icon(Icons.Filled.Menu, null)
}
},
title = {
Text("stars-one的测试应用")
},actions = {
IconButton(
onClick = {}
) {
Icon(Icons.Filled.Share, null)
}
IconButton(
onClick = {}
) {
Icon(Icons.Filled.Settings, null)
}
}
)
},
floatingActionButton = {
FloatingActionButton(onClick = { /*TODO*/ }) {
Icon(imageVector = Icons.Default.Favorite, contentDescription = null)
}
},
bottomBar = {
BottomAppBar(cutoutShape = CircleShape) {
}
},
//注意此参数,可以实现图中那种被裁剪的效果,前提是上面的cutoutShape也有设置
isFloatingActionButtonDocked = true,
floatingActionButtonPosition = FabPosition.End
) {
//这里是主界面
Text("我是要展示的内容")
}
效果如下图所示

底部导航条
我们在上面的基础改下即可(主要是bottomAppBar这个参数),代码如下所示
//当前选择的NavItem
var selectIndex by remember { mutableStateOf(0) }
val navTextList = listOf("主页", "发现", "我的")
//图标
val iconList = listOf(Icons.Default.Home,Icons.Default.Favorite,Icons.Default.AccountBox)
Scaffold(
topBar = {
TopAppBar(
navigationIcon = {
IconButton(
onClick = {}
) {
Icon(Icons.Filled.Menu, null)
}
},
title = {
Text("stars-one的测试应用")
},actions = {
IconButton(
onClick = {}
) {
Icon(Icons.Filled.Share, null)
}
IconButton(
onClick = {}
) {
Icon(Icons.Filled.Settings, null)
}
}
)
},
floatingActionButton = {
FloatingActionButton(onClick = { /*TODO*/ }) {
Icon(imageVector = Icons.Default.Add, contentDescription = null)
}
},
bottomBar = {
BottomNavigation() {
navTextList.forEachIndexed { index, str ->
BottomNavigationItem(label = {Text(str)},selected = index==selectIndex , onClick = {selectIndex = index },icon = {
Icon(imageVector = iconList[index], contentDescription = null)
})
}
}
},
//注意此参数,可以实现图中那种被裁剪的效果,前提是上面的cutoutShape也有设置
floatingActionButtonPosition = FabPosition.End
) {
//这里是主界面
//根据底部导航选中的下标改变展示的页面
when(selectIndex){
0 -> Text("这是首页")
1 -> Text("这是发现")
2 -> Text("这是我的")
}
}
效果如下图所示

带侧边抽屉
这里需要注意的是,弹出侧边抽屉是个挂起操作(suspend),所以需要使用到Kotlin中的协程,不过不是涉及太深,我们先知道怎么用即可,后面有空我再补充协程的用法
这里主要是测试了带drawer开头的那几个参数,及点击左上角的菜单按钮弹出侧边抽屉功能(即对应的点击事件)
//状态
val scaffoldState = rememberScaffoldState()
//协程的作用域
val scope = rememberCoroutineScope()
//当前选择的NavItem
var selectIndex by remember { mutableStateOf(0) }
val navTextList = listOf("主页", "发现", "我的")
//图标
val iconList =
listOf(Icons.Default.Home, Icons.Default.Favorite, Icons.Default.AccountBox)
Scaffold(
scaffoldState = scaffoldState,
topBar = {
TopAppBar(
navigationIcon = {
IconButton(
onClick = {
//使用协程
scope.launch {
//改变状态,显示drawer抽屉
scaffoldState.drawerState.open()
}
}
) {
Icon(Icons.Filled.Menu, null)
}
},
title = {
Text("stars-one的测试应用")
}, actions = {
IconButton(
onClick = {}
) {
Icon(Icons.Filled.Share, null)
}
IconButton(
onClick = {}
) {
Icon(Icons.Filled.Settings, null)
}
}
)
},
floatingActionButton = {
FloatingActionButton(onClick = { /*TODO*/ }) {
Icon(imageVector = Icons.Default.Add, contentDescription = null)
}
},
bottomBar = {
BottomNavigation() {
navTextList.forEachIndexed { index, str ->
BottomNavigationItem(
label = { Text(str) },
selected = index == selectIndex,
onClick = { selectIndex = index },
icon = {
Icon(
imageVector = iconList[index],
contentDescription = null
)
})
}
}
},
//注意此参数,可以实现图中那种被裁剪的效果,前提是上面的cutoutShape也有设置
floatingActionButtonPosition = FabPosition.End,
drawerContent = {
Text("这是抽屉的内容")
},
drawerContentColor = Color.Black,
drawerBackgroundColor = Color.Green,
drawerGesturesEnabled = true,
drawerScrimColor = Color.Red,
drawerShape = RoundedCornerShape(20.dp)
) {
//这里是主界面
//根据底部导航选中的下标改变展示的页面
when (selectIndex) {
0 -> Text("这是首页")
1 -> Text("这是发现")
2 -> Text("这是我的")
}
}


参考
Jetpack Compose学习(7)——MD样式架构组件Scaffold及导航底部菜单的更多相关文章
- Jetpack Compose学习(5)——从登录页美化开始学习布局组件使用
原文:Jetpack Compose学习(5)--从登录页美化开始学习布局组件使用 | Stars-One的杂货小窝 本篇主要讲解常用的布局,会与原生Android的布局控件进行对比说明,请确保了解A ...
- Jetpack Compose学习(2)——文本(Text)的使用
原文: Jetpack Compose学习(2)--文本(Text)的使用 | Stars-One的杂货小窝 对于开发来说,文字最为基础的组件,我们先从这两个使用开始吧 本篇涉及到Kotlin和DSL ...
- Jetpack Compose学习(3)——图标(Icon) 按钮(Button) 输入框(TextField) 的使用
原文地址: Jetpack Compose学习(3)--图标(Icon) 按钮(Button) 输入框(TextField) 的使用 | Stars-One的杂货小窝 本篇分别对常用的组件:图标(Ic ...
- Jetpack Compose学习(8)——State及remeber
原文地址: Jetpack Compose学习(8)--State状态及remeber关键字 - Stars-One的杂货小窝 之前我们使用TextField,使用到了两个关键字remember和mu ...
- Jetpack Compose学习(1)——从登录页开始入门
原文地址:Jetpack Compose学习(1)--从登录页开始入门 | Stars-One的杂货小窝 Jetpack Compose UI在前几天出了1.0正式版,之前一直还在观望,终于是出了正式 ...
- Jetpack Compose学习(6)——关于Modifier的妙用
原文: Jetpack Compose学习(6)--关于Modifier的妙用 | Stars-One的杂货小窝 之前学习记录中也是陆陆续续地将常用的Modifier的方法穿插进去了,本期就来详细的讲 ...
- Jetpack Compose学习(9)——Compose中的列表控件(LazyRow和LazyColumn)
原文:Jetpack Compose学习(9)--Compose中的列表控件(LazyRow和LazyColumn) - Stars-One的杂货小窝 经过前面的学习,大致上已掌握了compose的基 ...
- Jetpack Compose学习(4)——Image(图片)使用及Coil图片异步加载库使用
原文地址 Jetpack Compose学习(4)--Image(图片)使用及Coil图片异步加载库使用 | Stars-One的杂货小窝 本篇讲解下关于Image的使用及使用Coil开源库异步加载网 ...
- amazeui学习笔记--css(常用组件10)--导航条Topbar
amazeui学习笔记--css(常用组件10)--导航条Topbar 一.总结 1. 导航条:就是页面最顶端的导航条:在容器上添加 .am-topbar class,然后按照示例组织所需内容.< ...
随机推荐
- HttpURLconnection的介绍
一,HttpURLconnection的介绍 在Android开发中网络请求是最常用的操作之一, Android SDK中对HTTP(超文本传输协议)也提供了很好的支持,这里包括两种接口: 1.标准J ...
- 十九:JDBC操作事务
二.MySQL数据库中操作事务命令 2.1.开启事务(start transaction) 使用"start transaction"开启MySQL数据库的事务,如下所示:
- C# 委托讲解
首先,委托的使用场景:A的某些功能,只有在B需要触发时触发,委托就是用来做中间通讯的渠道. 假设:现在有个大佬A,A有个小弟B,B在受到羞辱时就会通过电话Delegate通知A自己被羞辱了,A在这时就 ...
- Spring parent 属性
Spring Framework Reference Documentation 6.7. Bean definition inheritance 注:本文中bean和definition意思等同 该 ...
- linux 常用命令(二)——(centos6.8-centos7)防火墙的启动、关闭
centos 6.8 [centos6.5]: 查看chkconfig列表里面是否有iptables的服务: chkconfig | grep iptables 查看防火墙状态: service ip ...
- Consul 入门-初识
背景 现状:单体架构逐渐被微服务架构所替代,原本两个功能模被拆分成了两个服务.原本两个模块块间的通信只需要函数调用就能够实现,现在却做不到了,因为它们不在同一个进程中,甚至两个服务都可能部署到不同的机 ...
- promise链式调用的应用
then在链式调用时,会等前一个then或者函数执行完毕,返回状态,才会执行回调函数. (1)代码顺序执行,第一步调用了函数cook ,cook执行返回了一个promise,promise返回的是成功 ...
- linux centos7 移动文件到指定目录
2021-08-26 在 centos7 环境下怎么移动一个文件到其他的目录下呢? 使用命令 mv 文件名 指定目录 即可完成该操作. 那么怎么将一个文件夹下的内容移动到另一个文件夹下呢?比如有时 ...
- vue 打开新窗口进行打印
父文件 let { href } = this.$router.resolve({ path: ' 自己配置本地路由,不需要动态路由 ', query: 个人建议传一整个对象 }) window.op ...
- SQLServer数据实时同步PostgreSQL
SQLServer数据实时同步至PostgreSQL 前言: 为迎合工作需求有时候传送的数据保存在SQLServer中但由于工作需要需要保存到PostgreSQL中进行处理,本文主要通过在SQLSer ...