# 准备知识
# JetpackCompose 相比传统 XML+Java 的优势
- 不需要多个 XML 和 Activity
- 可组合函数负责更新和构建页面
- 不需要通过 ID 来查找视图,而是通过视图来绑定
- 与 Java+XML 的传统方式相兼容
# 使用 JetpackCompe 构建页面
在 Andorid Studio 中新建项目,选择 Empty Compose Activity 后点击 Next
[img]
- 需要 API 21+
- 只能使用 Kotlin 语言
# AndoridManifest.xml 文件
1 |
|
application 内属性
- android:icon App 的主图标
- android:label 应用名称
- android:roundIcon 应用背景图标
- android:theme 应用的主题
activity 内属性:
- android:name 应用启动后的主页面
- android:label 应用名称
- android:theme 应用的主题
# 资源引用
1 | @[xxx]/[xxxx] |
- [xxx] 为引用资源的路径
- [xxxx] 为引用资源的名称,不包括文件后缀
如在 string.xml 内定义的应用名称:
1 | <resources> |
在其他位置的引用可以使用:
1 | @string/app_name |
# 依赖项
在 build.gradle(:app) (注:作用域是 app) 下的 dependencies 组为依赖项,可以在这里添加你需要使用的库
# 案例 1 个人页面
完整代码如下:
1 | package com.candy.ui_test |
# 布局
# Column 垂直布局
1 | import androidx.compose.foundation.layout.Column |
一种纵向的列表布局
参数
- verticalArrangement 垂直对齐方式 属性值为 Arrangement.[direction]
- horizontalAlignment 水平对齐方式 属性值为 Alignment.[direction]
- content ?
modifier 参数
- .fillMaxSize/Widht/Height() 列表填满父容器 (宽度 / 高度)
- .padding([int.dp]) 外边距
- .margin([int.dp]) 内边距
- .requiredHeight(Weight) 强制设置高度 / 宽度 (不受父高度影响强制设置)
# Row 水平布局
1 | import androidx.compose.foundation.layout.Row |
一种纵向的列表布局
参数
- verticalArrangement 垂直对齐方式 属性值为 Arrangement.[direction]
- horizontalAlignment 水平对齐方式 属性值为 Alignment.[direction]
- content ?
modifier 参数
- .fillMaxSize/Widht/Height() 列表填满父容器 (宽度 / 高度)
- .padding([int.dp]) 外边距
- .margin([int.dp]) 内边距
- .requiredHeight(Weight) 强制设置高度 / 宽度 (不受父高度影响强制设置)
# Card 卡片布局
1 | import androidx.compose.material3.Card |
一种卡片形式的布局
参数
- shape 卡片形状
- colors 卡片颜色
- elevation 卡片悬浮高度 (MD3:
CardDefaults.cardElevation(defaultElevation = [int].dp)
; MD2:[int].dp
) int 值为阴影模糊程度 - border 卡片边框线
- content ?
modifier 参数
- .fillMaxSize/Widht/Height() 列表填满父容器 (宽度 / 高度)
- .padding([int.dp/sp]) 外边距 (可以分开设置 top bottom start end)
- .height([int.dp]) 卡片高度
- .weight([int.dp]) 卡片宽度
- .requiredHeight(Weight) 强制设置高度 / 宽度 (不受父高度影响强制设置)
# 约束布局
1 | import androidx.constraintlayout.compose.ConstraintLayout |
一种使用 ID 来绑定组件的布局,可以更方便的定义组件所在页面中的位置
而在这种布局下, horizontalAlignment
和 verticalArrangement
不再可用
要使用约束布局,需要在 build.gradle
中添加依赖项:
1 | implementation ("androidx.constraintlayout:constraintlayout-compose:1.1.1") |
截至写这篇文章的时候,最新的版本为 1.1.1 Constraintlayout | Jetpack | Android Developers
要使用约束布局,需要按以下方式:
- 使用
createRefs()
或createRefFor()
为ConstraintLayout
中的每个可组合项创建引用 - 约束条件使用
Modifier.constrainAs()
修饰符提供的,该修饰符将引用作为参数,然后指定其约束条件 - 约束条件使用
linkTo()
方法指定 parent
是一个屏幕位置,可用于指定对ConstraintLayout
可组合项本身的约束条件
modifier 参数
由 .constrainAs([String id])
控制
- top.linkTo() 顶部链接到
- buttom.linkTo() 底部链接到
- start.linkTo() 起始处链接到
- end.linkTo() 结尾处链接到
- width 属性值 (如 Dimension.wrapContent*)
该项目中所有参数均为所设定的控件 ID 其中,parent 为父级,可以理解为屏幕
* 使用 Dimension.wrapContent 需要导入
1 | import androidx.constraintlayout.compose.Dimension |
# 约束布局的解耦合
优势:有助于实现横屏和竖屏的切换
-
首先需要导入一个盒子约束容器
-
在其内部定义一个变量,通过判断来判断用户当前为横屏还是竖屏,接着设置约束方法函数
而在该约束容器内部的约束布局内的元素需要给 Modifier 注册.layoutId (“String”),并在约束方法中引用
比如导入
1 | import androidx.compose.foundation.layout.BoxWithConstraints |
BoxWithConstraints 约束盒子容器
# 约束方法
创建一个保护的成员函数
# Scaffold "脚手架" 布局
1 | import androidx.compose.material3.Scaffold |
Scaffold 是一种类似于框架一样的结构。它将界面的不同部分整合在一起,使其具有一致的外观和风格
- topBar 应用的屏幕顶部应用栏
- bottom 应用的屏幕底部应用栏
- floatingActionButton 悬浮在屏幕右下角的按钮
Scaffold 会自动计算举例宽度,所以在该可组合函数内部要使用 innerPadding->
来传入边距

** 案例 (来自谷歌官方): **
1 |
|
官方文档: Scaffold - Jetpack Compose | Android Developers
# LazyColumn / LazyRow "懒" 列 / 行布局
1 | import androidx.compose.foundation.lazy.LazyColumn |
这是一个可以扩展长度的容器,在该容器内的元素必须是动态长度
需要使用 item lambda 等遍历容器
1 | val itemsList = (0..5).toList() |
# Box 盒子布局
1 | import androidx.compose.foundation.layout.Box |
可以层叠元素的盒子,类似于 HTML 中的 div 标签
# 控件
# Text 文本组件
1 | import androidx.compose.material3.Text |
一种显示文本的文本组件
参数
- text 文本内容,类型为 String
- color 文本颜色
- fontSize([int].dp) 文字大小
- fontStyle 文本风格?
- fontWeight 字体粗细,由
FontWeight
类控制 - fontFamily 字体家族,由
FontFamily
类控制 - textAlign 文本对齐方式?
# Image 图像组件
1 | import androidx.compose.foundation.Image |
一种显示图像的组件
- painter 画家 (图像路径)
- contentDescription 图像的描述 (针对视障人士)
- contentScale 图片的裁剪方式 (如填充横向 填充纵向等等)
- alignment 对齐方式 (默认居中)
- alpha 不透明度 (单位 Float)
** 官方文档: ** 加载图片 | Jetpack Compose | Android Developers
modifier 参数
- .size 图片尺寸 / 大小 (单位 dp)
- .clip 图片形状 [如
CircleShape
为纯圆,可以使用RoundedCornerShape([int].dp)
自定义圆角] - .border 图片边框
** 官方文档: ** 自定义图片 | Jetpack Compose | Android Developers
# TextField 文本输入框
1 | import androidx.compose.material3.TextField |
一种用于让用户输入的文本框有多种样式可选
-
TextField 基础的默认的样式,样式为填充
-
OutlinedTextField 轮廓样式版本,无填充
-
SecureTextField 安全输入,用于输入密码等
-
value 输入框内的值
-
onValueChange 当输入框内容变更后执行
-
label 输入框提示值
以下是一个案例,当用户输入内容更新后将用户输入的内容输出在 UI 中
1 | var name_state by remember { |
官方文档: 配置文本字段 | Jetpack Compose | Android Developers
# Spacer 空行分隔符
1 | import androidx.compose.foundation.layout.Spacer |
modifier 参数
- .size 大小
- .weight 空行的宽度
- .height 空行的高度
# Icon 图标组件
1 | import androidx.compose.material3.Icon |
- imageVector 图标名 谷歌官方提供的图标都在
Icons.
类下 - contentDescription 无障碍提示
- tint 应用于
imageVector
, 如果提供了Color.[name]
, 则不应用色调
# NavigationBar 底部导航栏
1 | import androidx.compose.material3.NavigationBar |
- containerColor 底部导航栏的背景色
- contentColor 底部导航栏的文字 / 图标的颜色
# NavigationBarItem 导航栏图标按钮
1 | import androidx.compose.material3.NavigationBarItem |
- selected 是否选中
- onClick 点击事件,常用于导航跳转
- icon 按钮图标
- label 文本内容
这俩常用在一起,用于给 Scaffold
添加 bottomBar
1 | NavigationBar( |
通常来说会将图标和文字放在别处
- 创建一个包 model
- 新建一个 kotlin 类
- 在类中创建对象,并在导航栏中引用
# IconButton 按钮图标组件
1 | import androidx.compose.material3.IconButton |
- onClick 点击事件
- enabled 启用按钮 (默认为 true)
- colors 按钮的颜色
可以在内部设置 Icon 图标和文字
1 | IconButton( |
# Dialog 对话框组件
1 | import androidx.compose.ui.window.Dialog |
- onDismissrequest 用户关闭对话框(例如点按对话框以外的任意位置)时调用
- properties 一个
DialogProperties
实例,可提供一些额外的自定义范围
1 | import androidx.compose.ui.window.DialogProperties //使用DialogProperties需要导入 |
# AlertDialog 提醒对话框组件
1 | import androidx.compose.material3.AlertDialog |
这是一个便捷的 API,用于创建一个简易的对话框,如取消确认等
- title 对话框标题
- text 对话框内说明文本
- icon 对话框顶部显示的图标
- onDismissrequest 用户关闭对话框(例如点按对话框以外的任意位置)时调用
- dismissButton 用于关闭的可组合函数
- confirmButton 用于确认的可组合函数
以下是谷歌官方案例:
1 |
|
官方文档: 对话框 | Jetpack Compose | Android Developers
# xxxDivider 分割线组件
- HorizontalDivider 水平分割线
- VerticalDivider 垂直分割线
组件参数:
- thickness 使用此参数指定分隔线的粗细。
- color 使用此参数指定分隔线的颜色。
官方文档: 分隔线 | Jetpack Compose | Android Developers
# Chip 条状标签
1 | import androidx.compose.material3.Chip |
有多种样式可选
-
onClick 设定点击状态
-
label 设定显示文字 需要 Composable 函数
-
selected 是否选中
-
leadingIcon 定义菜单项中前方显示的图标 需要 Compose 函数
-
trailingIcon 定义菜单项中后方显示的图标 需要 Compose 函数
1 | var select by remember { mutableStateOf(false) } |
官方文档: 条状标签 | Jetpack Compose | Android Developers
# DropdownMenu 下拉菜单
- expanded 菜单是否可见
- onDismissRequest 处理菜单关闭
# DropdownMenuItem 下拉菜单选项
- onClick 点击菜单项后执行
- text 定义菜单项中显示的内容 需要 Compose 函数而不是 String
- leadingIcon 定义菜单项中前方显示的图标 需要 Compose 函数
- trailingIcon 定义菜单项中后方显示的图标 需要 Compose 函数
1 | var menuExpanded by remember { mutableStateOf(false) } |
官方文档: 菜单 | Jetpack Compose | Android Developers
#
# Modifier 修饰符
Compose 修饰符列表 | Jetpack Compose | Android Developers
# 状态
在 Jetpack 中,我们需要使用 remember 关键字来设置一个可变状态
# 可变状态
# remember
remember
是一个 Composable 函数,它用于在重组过程中记住一个值。当一个 Composable 重组时, remember
会返回它在上次重组时记住的相同值。如果没有 remember
, 每次重组时,局部变量都会被重新初始化而导致状态丢失
若需使用 remember 需要导入:
1 | import androidx.compose.runtime.getValue |
# mutableStateOf
mutableStateOf
是一个函数,用于创建一个 MutableState
实例。其接收一个初始值,并返回一个可观察的对象。当 MutableState
的 value
改变时,所有读取该 value
的 Composable 都会被标记为需要重组
在函数体中, mutableStateOf
为创建一个可观察的 MutableState<T>
对象。当 MutableState
中的值改变时,Compose 会自动触发依赖该状态的可组合函数的重组
声明 MutableState
对象的方法有如下 (default 为默认值):
val mutableState = remember { mutableStateOf(default) }
var value by remember { mutableStateOf(default) }
val (value, setValue) = remember { mutableStateOf(default) }
例如:
1 | var name_state by remember { |
官方文档: 状态和 Jetpack Compose | Android Developers
# 导航
导航 | App architecture | Android Developers