Jetpack Compose 从入门到精通
一、基础篇
1. 什么是 Compose
Jetpack Compose 是 Google 推出的Android 原生声明式 UI 框架,替代传统 XML + View 体系:
- 命令式 UI(XML):先布局文件,代码 findViewById 找控件,调用
setText/setVisibility修改状态 - 声明式 UI(Compose):用纯 Kotlin 函数描述界面,状态驱动 UI 自动刷新,数据变界面自动重绘
核心优势:
- 代码更少,无 xml、无 id、无 findViewById、无 inflate
- 天然适配 Kotlin 特性(lambda、高阶函数、空安全)
- 内置主题、暗黑模式、动画、手势、组件库
- 跨平台复用逻辑(Desktop Compose、iOS Compose Multiplatform)
2. 环境准备
版本要求
- Android Studio Giraffe 及以上(新版内置 Compose 模板)
- AGP ≥ 8.0,Kotlin ≥ 1.9,JDK 17
- 最低兼容 API 21(Android 5.0),完整特性建议 minSdk 24+
新建 Compose 项目
New Project → 选择 Empty Activity (Jetpack Compose) 自动生成依赖(build.gradle Module 层):
gradle
android {
namespace "com.example.composelearn"
compileSdk 35
defaultConfig {
applicationId "com.example.composelearn"
minSdk 24
targetSdk 35
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {
useSupportLibrary true
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = '17'
}
buildFeatures {
compose true // 开启Compose编译
}
composeOptions {
kotlinCompilerExtensionVersion "1.9.0" // 和Kotlin版本对应
}
packaging {
resources {
excludes += '/META-INF/{AL2.0,LGPL2.1}'
}
}
}
dependencies {
// Compose BOM 统一版本管理(推荐)
implementation platform('androidx.compose:compose-bom:2026.02.00')
implementation 'androidx.compose.ui:ui'
implementation 'androidx.compose.ui:ui-graphics'
implementation 'androidx.compose.ui:ui-tooling-preview'
implementation 'androidx.compose.material3:material3' // Material3 新版组件库
implementation 'androidx.activity:activity-compose:1.9.0' // Activity 挂载Compose入口
// 调试工具
debugImplementation 'androidx.compose.ui:ui-tooling'
debugImplementation 'androidx.compose.ui:ui-test-manifest'
}
3. 第一个 Compose 程序
3.1 @Composable 可组合函数核心规则
定义规则
- 函数必须添加注解:
@Composable - 无返回值 (返回
Unit) - 约定规范:函数名首字母大写(区分普通函数)
- 只能在
@Composable函数内部调用另一个@Composable函数 - 不能放在循环、if 判断分支以外随意调用(遵循重组规则)
正确写法 vs 错误写法
kotlin
// ✅ 正确
@Composable
fun HelloText() {
Text("Hello Compose")
}
// ❌ 错误:小写、缺少注解
fun wrongFunc() {
Text("test")
}
Activity 挂载入口
setContent 是唯一入口,所有 Compose 组件都写在里面:
kotlin
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
// 全局主题包裹(自动生成的MyAppTheme)
MyAppTheme {
HelloText()
}
}
}
}
3.2 @Preview 可视化预览(不用跑模拟器)
3.2.1 使用规则
- 注解:
@Preview - 修饰
@Composable函数 - 预览函数不能带参数,要调用真正的 UI 组件传参
- 点击侧边 Split 分栏,实时看效果
3.2.2 完整预览模板
kotlin
// 可预览的包装函数(无参数)
@Preview(showBackground = true, widthDp = 360, heightDp = 600)
@Composable
fun BasicAllPreview() {
MyAppTheme {
Column(Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(16.dp)) {
HelloText()
ColumnSample()
RowSample()
BoxSample()
TextSample()
ButtonSample()
TextFieldSample()
}
}
}
3.2.3 @Preview 常用参数
showBackground = true:显示灰色背景,看得更清楚widthDp/heightDp:固定预览窗口大小showSystemUi = true:显示状态栏、导航栏模拟真机
3.2.4 操作方式
- 写完
@Preview后,函数左侧会出现 小眼睛图标 - 点击 → Render Preview 自动渲染 UI
- 修改代码,预览实时刷新,极大提升调试效率
3.3 入口规则
- 带
@Composable注解的 Kotlin 函数 = UI 组件 - 函数无返回值、首字母大写(规范)
setContent是 Activity 挂载 Compose 根节点
kotlin
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// 根Compose容器
setContent {
MyAppTheme { // 全局主题包裹
Greeting("Hello Jetpack Compose")
}
}
}
}
// 可组合函数 @Composable
@Composable
fun Greeting(text: String) {
// Text 基础文本组件
Text(
text = text,
fontSize = 24.sp,
color = Color.Blue
)
}
// 预览注解,Split窗口直接看UI效果
@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
MyAppTheme {
Greeting("预览文本")
}
}
快捷键:点击 @Preview 旁小图标打开可视化预览。
二、核心基础组件(布局 + 基础控件)
1. 三大基础布局Row / Column / Box
对应传统 XML:
- Column ≈ LinearLayout 垂直
- Row ≈ LinearLayout 水平
- Box ≈ FrameLayout 层叠堆叠
Row 水平布局(横向排列)
kotlin
@Composable
fun RowDemo() {
Row(
horizontalArrangement = Arrangement.SpaceEvenly, // 水平分布
verticalAlignment = Alignment.CenterVertically // 垂直居中
) {
Text("A")
Text("B")
Text("C")
}
}
Column 垂直布局(纵向排列)
kotlin
@Composable
fun ColumnDemo() {
Column(
modifier = Modifier.padding(20.dp),
verticalArrangement = Arrangement.Top,
horizontalAlignment = Alignment.Start
) {
Text("第一行")
Text("第二行")
}
}
常用
verticalArrangement:
Top/Center/Bottom/SpaceBetween/SpaceAround/SpaceEvenly
Box 层叠布局(FrameLayout)
kotlin
@Composable
fun BoxDemo() {
Box(
modifier = Modifier.size(200.dp)
) {
Box(Modifier.fillMaxSize().background(Color.Gray))
Text("悬浮文字", Modifier.align(Alignment.Center))
}
}
对齐方式:
align(Alignment.TopStart/Center/BottomEnd)
2. Modifier 修饰器(Compose 灵魂)
所有组件通过 Modifier 设置样式、尺寸、背景、内边距、点击、滚动等,链式调用:
常用方法:
kotlin
Text(
text = "Modifier完整示例",
modifier = Modifier
.padding(16.dp) // 四周内边距
.padding(horizontal = 20.dp) // 左右边距
.fillMaxWidth() // 占满父宽度
.height(50.dp) // 固定高度
.background(
color = Color.Cyan,
shape = RoundedCornerShape(12.dp) // 圆角矩形
)
.clip(RoundedCornerShape(12.dp)) // 裁剪圆角
.shadow(6.dp, RoundedCornerShape(12.dp)) // 阴影
.clickable { // 点击事件
println("点击了文本")
}
)
重点:
- 顺序影响效果:先
background再shadow和反过来不一样 dp是尺寸单位,sp只用于文字字号
3. 常用基础控件 Text / Button / TextField/Image
3.1 Text 文本:字体、颜色、行高、字符串资源
kotlin
@Composable
fun TextSample() {
Text(
text = "Jetpack Compose 文本",
fontSize = 22.sp,
color = Color(0xFF2196F3),
maxLines = 2,
overflow = TextOverflow.Ellipsis,
fontWeight = FontWeight.Bold
)
}
3.2 Image 图片加载
kotlin
Image(
painter = painterResource(id = R.drawable.ic_launcher),
contentDescription = "图标",
modifier = Modifier.size(80.dp)
)
3.3 Button / OutlinedButton / TextButton 按钮
kotlin
Button(onClick = { /* 点击逻辑 */ }) {
Text("普通按钮")
}
//三种常用样式:
@Composable
fun ButtonSample() {
Column(Modifier.padding(20.dp), verticalArrangement = Arrangement.spacedBy(10.dp)) {
// 填充按钮
Button(onClick = { /* 点击逻辑 */ }) {
Text("主要按钮")
}
// 边框按钮
OutlinedButton(onClick = {}) {
Text("边框按钮")
}
// 文字按钮
TextButton(onClick = {}) {
Text("文字按钮")
}
}
}
//`spacedBy(10.dp)`:子组件之间统一间距,替代重复写 padding。
3.4 TextField 输入框(文本输入: 受控组件)
kotlin
@Composable
fun TextFieldSample() {
// remember 保存状态,mutableStateOf 可观察变量,
// `by` 委托语法简化 `.value` 写法
var inputContent by remember { mutableStateOf("") }
TextField(
value = inputContent,
onValueChange = { newText ->
inputContent = newText
},
label = { Text("请输入用户名") },
placeholder = { Text("提示文字") },
modifier = Modifier.fillMaxWidth().padding(horizontal = 20.dp)
)
}
必须配合状态使用
三、核心原理:状态管理(重中之重)
Compose UI 完全依赖State 状态驱动,状态改变自动重组(recomposition)刷新界面。
1. 基础 remember + mutableStateOf
remember:在组件重组时保存变量,不会被重置 mutableStateOf:创建可观察状态,修改触发 UI 刷新
kotlin
@Composable
fun CounterDemo() {
// 计数器状态
var count by remember { mutableStateOf(0) }
Column(Modifier.padding(20.dp)) {
Text("计数:$count")
Button(onClick = { count++ }) {
Text("+1")
}
}
}
关键字
by委托写法,直接赋值;不加 by 需要.value:count.value++
2. 状态提升(单向数据流)
最佳实践:UI 组件只负责展示,状态由上层传入,解耦复用:
kotlin
// 纯展示组件,无内部状态
@Composable
fun CountView(count: Int, onAdd: () -> Unit) {
Column {
Text("计数 $count")
Button(onClick = onAdd) { Text("加") }
}
}
// 父组件持有状态
@Composable
fun ParentPage() {
var count by remember { mutableStateOf(0) }
CountView(count = count, onAdd = { count++ })
}
3. 复杂状态:data class + mutableStateOf
kotlin
data class User(var name: String, var age: Int)
@Composable
fun UserStateDemo() {
var user by remember { mutableStateOf(User("张三", 20)) }
Column {
Text("姓名:${user.name} 年龄:${user.age}")
Button(onClick = { user = user.copy(age = user.age + 1) }) {
Text("长大一岁")
}
}
}
⚠️ 必须用 copy 创建新对象,Compose 靠对象引用变化感知更新。
4. 状态存储方案层级(由简单到项目级)
remember:临时页面内状态,页面销毁丢失rememberSaveable:横竖屏旋转、系统进程重启保存状态- ViewModel:跨生命周期、跨组件共享状态(企业项目标配)
- 持久化:DataStore / Room 本地磁盘存储
ViewModel 在 Compose 中使用
- 依赖添加
gradle
implementation "androidx.lifecycle:lifecycle-viewmodel-compose:2.8.0"
- ViewModel 类
kotlin
class CountViewModel : ViewModel() {
private val _count = MutableStateFlow(0)
val count = _count
fun add() {
_count.value += 1
}
}
- Compose 中调用
kotlin
@Composable
fun ViewModelDemo() {
val vm: CountViewModel = viewModel()
val count by vm.count.collectAsStateWithLifecycle()
Column {
Text("ViewModel计数:$count")
Button(onClick = { vm.add() }) {
Text("增加")
}
}
}
collectAsStateWithLifecycle 绑定生命周期,避免后台无效订阅。
四、进阶布局与滚动、列表
1. 滚动容器
VerticalScroll纵向滚动 ColumnHorizontalScroll横向滚动 Row
kotlin
Column(
Modifier.verticalScroll(rememberScrollState())
) {
// 超长内容自动滚动
}
2. Lazy 高性能列表(替代 RecyclerView)
Compose 懒加载列表,只渲染屏幕可见 Item,性能等同 RecyclerView
LazyColumn 垂直列表
kotlin
@Composable
fun LazyListDemo() {
val list = List(100) { "条目 $it" }
LazyColumn(Modifier.fillMaxSize()) {
items(list) { item ->
Text(
text = item,
Modifier.padding(16.dp).fillMaxWidth()
)
}
}
}
其他懒加载组件:
LazyRow横向列表LazyVerticalGrid网格布局(GridView)LazyHorizontalGrid横向网格
五、导航、路由与页面跳转(Navigation Compose)
1. 依赖
gradle
implementation "androidx.navigation:navigation-compose:2.8.0"
2. 基础多页面跳转完整示例
kotlin
// 定义路由常量
object Route {
const val HOME = "home"
const val DETAIL = "detail/{id}"
}
@Composable
fun AppNavHost() {
val navController = rememberNavController()
NavHost(
navController = navController,
startDestination = Route.HOME
) {
// 首页页面
composable(Route.HOME) {
HomePage { id ->
navController.navigate("detail/$id")
}
}
// 详情页,接收参数
composable(
Route.DETAIL,
arguments = listOf(navArgument("id") { type = NavType.IntType })
) { backStackEntry ->
val id = backStackEntry.arguments?.getInt("id") ?: 0
DetailPage(id) {
navController.popBackStack() // 返回上一页
}
}
}
}
// 首页
@Composable
fun HomePage(onGoDetail: (Int) -> Unit) {
Button(onClick = { onGoDetail(1001) }) {
Text("跳转到详情页")
}
}
// 详情页
@Composable
fun DetailPage(id: Int, onBack: () -> Unit) {
Column(Modifier.padding(20.dp)) {
Text("收到参数ID:$id")
Button(onClick = onBack) {
Text("返回")
}
}
}
在 Activity 根节点调用 AppNavHost() 即可实现单 Activity 多页面架构。
六、高级特性篇
1. 主题系统 Material3
项目自动生成 Theme.kt,统一管理:
- 主色、辅色、背景色
- 字体样式 Typography
- 暗黑模式自动切换
kotlin
MaterialTheme(
colorScheme = if (isDark) DarkColorScheme else LightColorScheme,
typography = Typography,
shapes = Shapes
) {
// 页面内容
}
2. Compose 动画
简单数值动画 animateDpAsState
kotlin
@Composable
fun AnimateSizeDemo() {
var expand by remember { mutableStateOf(false) }
val size by animateDpAsState(targetValue = if (expand) 200.dp else 80.dp)
Box(
Modifier
.size(size)
.background(Color.Red)
.clickable { expand = !expand }
)
}
复杂动画:AnimatedVisibility 显示隐藏、animateContentSize 内容大小动画、Transition 多状态切换。
3. 手势与拖拽
Modifier.draggable、Modifier.pointerInput 自定义触摸、滑动、双指缩放。
4. Compose 与传统 View 混合使用
4.1 Compose 嵌套 XML View
kotlin
AndroidView(
factory = { context ->
LayoutInflater.from(context).inflate(R.layout.old_view, null)
}
)
4.2 XML 布局嵌套 Compose
xml
<androidx.compose.ui.platform.ComposeView
android:id="@+id/compose_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
kotlin
findViewById<ComposeView>(R.id.compose_view).setContent {
Text("嵌入在XML中的Compose")
}
5. 副作用函数(生命周期)
处理网络请求、资源释放、订阅监听,避免重组重复执行:
LaunchedEffect:协程副作用,页面启动执行、key 变化重启DisposableEffect:页面销毁时释放资源(解绑广播、关闭流)SideEffect:每次成功重组后执行rememberCoroutineScope:组件作用域协程
示例:进入页面请求网络
kotlin
@Composable
fun NetRequestDemo() {
var data by remember { mutableStateOf("加载中...") }
LaunchedEffect(Unit) { // Unit只执行一次
// 模拟网络请求
delay(1000)
data = "请求成功的数据"
}
Text(data)
}
七、工程化最佳实践(项目落地规范)
1. 代码分层架构
textile
com.xxx.compose
├── ui/ 页面层Compose组件
│ ├── home/
│ ├── mine/
│ └── common/ 通用封装组件(TopBar、EmptyView、Button封装)
├── viewmodel/ ViewModel层
├── repository/ 数据仓库
├── data/ 数据源(Api、Room、DataStore)
└── navigation/ 统一路由管理
2. 通用组件封装原则
- 原子组件:只接收参数,无内部硬编码状态
- 样式统一抽取:封装 Modifier 扩展函数、尺寸常量、颜色常量
kotlin
// 扩展函数示例
fun Modifier.cardStyle() = this
.fillMaxWidth()
.padding(8.dp)
.shadow(2.dp, RoundedCornerShape(12.dp))
.clip(RoundedCornerShape(12.dp))
.background(Color.White)
3. 性能优化关键点
- 减少不必要重组:稳定参数(添加
@Stable注解) - 大列表一律用
LazyColumn/LazyRow,禁止滚动 Column 加载上千条数据 - 图片使用
Coil加载(Compose 专用图片库)
gradle
implementation "io.coil-kt:coil-compose:2.6.0"
kotlin
AsyncImage(
model = "https://xxx.jpg",
contentDescription = null,
modifier = Modifier.size(120.dp)
)
- 避免在 Composable 函数内部创建对象、执行耗时计算,移入 ViewModel 或 remember 缓存
完整 Demo
kotlin
package com.example.composebasic
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.spacedBy
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.Button
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.TextField
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MyAppTheme {
MainBasicPage()
}
}
}
}
@Composable
fun MainBasicPage() {
Column(
modifier = Modifier
.fillMaxSize()
.padding(20.dp),
verticalArrangement = Arrangement.spacedBy(24.dp)
) {
HelloText()
ColumnSample()
RowSample()
BoxSample()
TextSample()
ButtonSample()
TextFieldSample()
}
}
@Composable
fun HelloText() {
Text("1. 第一个Compose组件", fontSize = 20.sp, fontWeight = FontWeight.Bold)
}
@Composable
fun ColumnSample() {
Column(Modifier.background(Color(0xFFF5F5F5)).padding(12.dp)) {
Text("Column 垂直布局1")
Text("Column 垂直布局2")
Text("Column 垂直布局3")
}
}
@Composable
fun RowSample() {
Row(
Modifier
.fillMaxWidth()
.background(Color(0xFFE3F2FD))
.padding(12.dp),
horizontalArrangement = Arrangement.SpaceAround
) {
Text("A")
Text("B")
Text("C")
}
}
@Composable
fun BoxSample() {
Box(
Modifier
.size(180.dp)
.background(Color.LightGray)
) {
Box(Modifier.fillMaxSize().background(Color.Blue.copy(alpha = 0.2f)))
Text("Box层叠居中", Modifier.align(Alignment.Center), fontSize = 16.sp)
Text("右下角", Modifier.align(Alignment.BottomEnd).padding(8.dp), fontSize = 12.sp)
}
}
@Composable
fun TextSample() {
Text(
text = "Text 文本控件,带颜色、加粗、单行省略效果测试超长文字超长文字超长文字",
fontSize = 18.sp,
color = Color(0xFFD81B60),
fontWeight = FontWeight.Medium,
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
}
@Composable
fun ButtonSample() {
Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
Button(onClick = {}) { Text("主按钮") }
OutlinedButton(onClick = {}) { Text("边框按钮") }
TextButton(onClick = {}) { Text("文字按钮") }
}
}
@Composable
fun TextFieldSample() {
var text by remember { mutableStateOf("") }
TextField(
value = text,
onValueChange = { text = it },
label = { Text("输入框演示") },
modifier = Modifier.fillMaxWidth()
)
}
@Preview(showBackground = true, widthDp = 380, heightDp = 900)
@Composable
fun PreviewAll() {
MyAppTheme {
MainBasicPage()
}
}
@Composable
fun MyAppTheme(content: @Composable () -> Unit) {
MaterialTheme {
content()
}
}
附赠:高频拓展方向
- Compose MVI 架构完整模板(需要我直接给一套可复制脚手架)
- 封装通用弹窗、加载框、顶部导航栏、下拉刷新
- 权限请求、文件读写、相机相册调用 Compose 封装
- Compose Multiplatform 一套代码跑 Android、iOS、桌面端