Jetpack Compose 是 Google 推出的现代声明式 UI 工具包,用于构建 Android 原生界面,基于 Kotlin 语言设计,彻底改变了传统的 XML 布局方式,实现了「代码即 UI」的开发模式。本文将从核心概念、基础语法、组件使用、状态管理、布局系统等维度,结合完整的 Kotlin 代码示例,详细讲解 Compose 的使用方式。
一、核心概念
1.1 声明式编程
Compose 采用声明式 UI 范式:开发者只需描述 UI 的「最终状态」,Compose 自动处理 UI 的构建、更新和渲染,而非传统命令式编程中手动操作 View 的创建和修改。
kotlin
// 声明式:描述"有一个文本,显示Hello Compose"
Text(text = "Hello Compose")
// 传统命令式(对比)
val textView = TextView(context)
textView.text = "Hello XML"
layout.addView(textView)
1.2 可组合函数(Composable)
Compose 的核心是可组合函数 ,通过 @Composable 注解标记,用于构建 UI 组件。
- 只能在其他可组合函数中调用
- 无返回值(专注描述 UI,而非返回 View)
- 支持参数传递,实现组件复用
1.3 重组(Recomposition)
当可组合函数的输入参数(状态)发生变化时,Compose 会重新执行该函数,更新 UI 中变化的部分(仅更新差异),这一过程称为「重组」,是 Compose 实现 UI 响应式更新的核心。
二、环境配置
2.1 基础依赖(build.gradle.kts)
确保项目使用 Android Gradle Plugin 7.0+,并添加以下依赖:
kotlin
plugins {
id("com.android.application") version "8.2.0" apply false
id("org.jetbrains.kotlin.android") version "1.9.0" apply false
}
// 模块级 build.gradle.kts
android {
compileSdk = 34
buildFeatures {
compose = true // 启用 Compose
}
composeOptions {
kotlinCompilerExtensionVersion = "1.5.3" // 与 Kotlin 版本匹配
}
}
dependencies {
// Compose 核心库
implementation("androidx.compose.ui:ui:1.5.4")
// Material Design 3(推荐)
implementation("androidx.compose.material3:material3:1.1.2")
// 预览功能
implementation("androidx.compose.ui:ui-tooling-preview:1.5.4")
// 活动集成
implementation("androidx.activity:activity-compose:1.8.2")
// 测试
androidTestImplementation("androidx.compose.ui:ui-test-junit4:1.5.4")
debugImplementation("androidx.compose.ui:ui-tooling:1.5.4")
}
2.2 入口 Activity
Compose 不再需要 XML 布局,Activity 只需设置 Compose 内容:
kotlin
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.ui.Modifier
import androidx.activity.compose.setContent
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// 设置 Compose 内容
setContent {
// 应用主题
MyComposeAppTheme {
// 填充整个屏幕
Surface(modifier = Modifier.fillMaxSize()) {
// 自定义可组合函数
Greeting(name = "Compose")
}
}
}
}
}
// 应用主题(自动生成,可自定义)
@Composable
fun MyComposeAppTheme(
darkTheme: Boolean = false,
content: @Composable () -> Unit
) {
val colorScheme = if (darkTheme) {
MaterialTheme.colorScheme
} else {
MaterialTheme.colorScheme
}
MaterialTheme(
colorScheme = colorScheme,
typography = MaterialTheme.typography,
content = content
)
}
三、基础可组合组件
3.1 文本(Text)
最基础的文本展示组件,支持样式、颜色、大小等配置:
kotlin
@Composable
fun Greeting(name: String) {
Text(
text = "Hello, $name!",
// 文本样式
style = MaterialTheme.typography.headlineMedium,
// 文本颜色
color = MaterialTheme.colorScheme.primary,
// 内边距
modifier = Modifier.padding(16.dp)
)
}
// 预览函数(无需运行应用即可查看 UI)
@Preview(showBackground = true, name = "Greeting Preview")
@Composable
fun GreetingPreview() {
MyComposeAppTheme {
Greeting("Android")
}
}
3.2 按钮(Button)
可点击的按钮组件,支持点击事件、禁用状态等:
kotlin
@Composable
fun ActionButton(onClick: () -> Unit) {
Button(
onClick = onClick,
// 禁用状态
enabled = true,
// 形状
shape = RoundedCornerShape(8.dp),
// 内边距
modifier = Modifier.padding(8.dp)
) {
// 按钮内的内容(文本+图标)
Row(verticalAlignment = Alignment.CenterVertically) {
Icon(
imageVector = Icons.Default.Send,
contentDescription = "Send icon",
modifier = Modifier.size(24.dp)
)
Spacer(modifier = Modifier.width(8.dp)) // 间距
Text(text = "Submit")
}
}
}
// 预览
@Preview
@Composable
fun ActionButtonPreview() {
MyComposeAppTheme {
ActionButton(onClick = { /* 点击逻辑 */ })
}
}
3.3 输入框(TextField)
文本输入组件,支持双向绑定、提示文本、验证等:
kotlin
@Composable
fun NameInputField() {
// 状态:用于双向绑定输入内容(remember 确保重组时状态不丢失)
var name by remember { mutableStateOf("") }
OutlinedTextField(
value = name,
onValueChange = { name = it }, // 双向绑定
label = { Text("Enter your name") }, // 标签
placeholder = { Text("e.g. John Doe") }, // 占位符
leadingIcon = { Icon(Icons.Default.Person, contentDescription = "Person icon") },
// 错误提示
isError = name.length < 3,
supportingText = {
if (name.length < 3) {
Text("Name must be at least 3 characters")
}
},
modifier = Modifier
.fillMaxWidth()
.padding(16.dp)
)
}
@Preview
@Composable
fun NameInputFieldPreview() {
MyComposeAppTheme {
NameInputField()
}
}
3.4 图片(Image)
加载本地/网络图片(网络图片需配合 Coil 库):
kotlin
// 本地图片
@Composable
fun LocalImage() {
Image(
painter = painterResource(id = R.drawable.ic_launcher_foreground),
contentDescription = "App icon", // 无障碍描述
modifier = Modifier
.size(64.dp)
.clip(CircleShape) // 圆形裁剪
)
}
// 网络图片(需添加 Coil 依赖:implementation("io.coil-kt:coil-compose:2.4.0"))
@Composable
fun NetworkImage(url: String) {
AsyncImage(
model = url,
contentDescription = "Network image",
modifier = Modifier.size(128.dp),
// 加载中占位符
placeholder = painterResource(id = R.drawable.placeholder),
// 错误占位符
error = painterResource(id = R.drawable.error)
)
}
四、布局系统
Compose 提供灵活的布局组件,核心布局包括:
4.1 线性布局(Row/Column)
Row:水平排列子组件Column:垂直排列子组件
kotlin
@Composable
fun LinearLayoutExample() {
Column(
// 垂直排列的对齐方式
verticalArrangement = Arrangement.SpaceBetween,
// 水平对齐方式
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
.fillMaxSize()
.padding(16.dp)
) {
Text(text = "Top Text", style = MaterialTheme.typography.titleLarge)
Row(
horizontalArrangement = Arrangement.Center,
modifier = Modifier.fillMaxWidth()
) {
Button(onClick = {}) { Text("Button 1") }
Spacer(modifier = Modifier.width(8.dp))
Button(onClick = {}) { Text("Button 2") }
}
Text(text = "Bottom Text", style = MaterialTheme.typography.titleLarge)
}
}
@Preview
@Composable
fun LinearLayoutPreview() {
MyComposeAppTheme {
LinearLayoutExample()
}
}
4.2 盒子布局(Box)
层叠布局,子组件可重叠,支持对齐方式:
kotlin
@Composable
fun BoxLayoutExample() {
Box(
modifier = Modifier
.size(200.dp)
.background(MaterialTheme.colorScheme.secondaryContainer),
contentAlignment = Alignment.Center
) {
// 底层组件
Image(
painter = painterResource(id = R.drawable.background),
contentDescription = null,
modifier = Modifier.fillMaxSize()
)
// 上层文本(覆盖在图片上)
Text(
text = "Overlay Text",
color = MaterialTheme.colorScheme.onSecondaryContainer,
style = MaterialTheme.typography.headlineSmall
)
}
}
4.3 滚动布局(Scrollable)
LazyColumn:垂直滚动列表(仅渲染可见项,性能优)LazyRow:水平滚动列表
kotlin
@Composable
fun LazyListExample() {
// 模拟数据
val items = List(50) { "Item $it" }
LazyColumn(
modifier = Modifier.fillMaxSize(),
contentPadding = PaddingValues(16.dp), // 列表内边距
verticalArrangement = Arrangement.spacedBy(8.dp) // 项间距
) {
// 头部
item {
Text(
text = "List Header",
style = MaterialTheme.typography.headlineSmall,
modifier = Modifier.padding(bottom = 16.dp)
)
}
// 列表项
items(items) { item ->
ListItem(
headlineContent = { Text(item) },
leadingContent = { Icon(Icons.Default.List, contentDescription = null) },
modifier = Modifier
.fillMaxWidth()
.background(MaterialTheme.colorScheme.surface)
.padding(8.dp)
)
}
}
}
@Preview
@Composable
fun LazyListPreview() {
MyComposeAppTheme {
LazyListExample()
}
}
五、状态管理
状态是驱动 UI 变化的核心,Compose 提供多种状态管理方式:
5.1 基础状态(remember + mutableStateOf)
remember 用于保存重组时的状态,mutableStateOf 创建可观察的状态:
kotlin
@Composable
fun CounterExample() {
// 计数状态:remember 确保重组时不重置,mutableStateOf 触发重组
var count by remember { mutableStateOf(0) }
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.padding(16.dp)
) {
Text(text = "Count: $count", style = MaterialTheme.typography.headlineMedium)
Row(spacedBy = 8.dp) {
Button(onClick = { count-- }) { Text("-") }
Button(onClick = { count++ }) { Text("+") }
}
}
}
5.2 跨组件状态(rememberSaveable)
rememberSaveable 可在配置变更(如屏幕旋转)时保留状态:
kotlin
@Composable
fun PersistentCounter() {
// 配置变更后仍保留状态
var count by rememberSaveable { mutableStateOf(0) }
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.padding(16.dp)
) {
Text(text = "Persistent Count: $count")
Button(onClick = { count++ }) { Text("Increment") }
}
}
5.3 状态提升(State Hoisting)
将状态从子组件提升到父组件,实现状态共享和单向数据流:
kotlin
// 子组件(无状态)
@Composable
fun ToggleButton(
isToggled: Boolean,
onToggle: () -> Unit
) {
Button(
onClick = onToggle,
colors = ButtonDefaults.buttonColors(
containerColor = if (isToggled) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.secondary
)
) {
Text(text = if (isToggled) "On" else "Off")
}
}
// 父组件(管理状态)
@Composable
fun ToggleContainer() {
var isToggled by remember { mutableStateOf(false) }
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.padding(16.dp)
) {
ToggleButton(isToggled = isToggled, onToggle = { isToggled = !isToggled })
Text(text = "Current State: ${if (isToggled) "Active" else "Inactive"}")
}
}
六、高级特性
6.1 动画(Animation)
Compose 内置简洁的动画 API,支持属性动画、过渡动画等:
kotlin
@Composable
fun AnimatedBox() {
var expanded by remember { mutableStateOf(false) }
// 动画尺寸:从 100.dp 到 200.dp
val size by animateDpAsState(
targetValue = if (expanded) 200.dp else 100.dp,
animationSpec = tween(durationMillis = 500) // 动画时长
)
Box(
modifier = Modifier
.size(size)
.background(MaterialTheme.colorScheme.primary)
.clickable { expanded = !expanded },
contentAlignment = Alignment.Center
) {
Text(text = if (expanded) "Expanded" else "Collapsed", color = MaterialTheme.colorScheme.onPrimary)
}
}
6.2 主题自定义
扩展 Material Theme,自定义颜色、字体、形状:
kotlin
// 自定义颜色方案
private val MyColorScheme = lightColorScheme(
primary = Color(0xFF6200EE),
secondary = Color(0xFF03DAC6),
surface = Color.White,
onPrimary = Color.White
)
// 自定义字体
private val MyTypography = Typography(
headlineLarge = TextStyle(
fontFamily = FontFamily.Default,
fontSize = 32.sp,
fontWeight = FontWeight.Bold
),
bodyMedium = TextStyle(
fontSize = 16.sp,
lineHeight = 24.sp
)
)
// 自定义主题
@Composable
fun MyCustomTheme(content: @Composable () -> Unit) {
MaterialTheme(
colorScheme = MyColorScheme,
typography = MyTypography,
shapes = MaterialTheme.shapes,
content = content
)
}
// 使用自定义主题
@Preview
@Composable
fun CustomThemePreview() {
MyCustomTheme {
Column {
Text(text = "Custom Theme Text", style = MaterialTheme.typography.headlineLarge)
Button(onClick = {}) { Text("Custom Button") }
}
}
}
6.3 导航(Navigation)
集成 Jetpack Navigation 实现页面跳转:
kotlin
// 1. 添加依赖
// implementation("androidx.navigation:navigation-compose:2.7.6")
// 2. 定义路由
sealed class Screen(val route: String) {
object Home : Screen("home")
object Detail : Screen("detail/{itemId}") {
fun createRoute(itemId: Int) = "detail/$itemId"
}
}
// 3. 导航组件
@Composable
fun AppNavHost() {
val navController = rememberNavController()
NavHost(
navController = navController,
startDestination = Screen.Home.route
) {
composable(Screen.Home.route) {
HomeScreen(
onItemClick = { itemId ->
navController.navigate(Screen.Detail.createRoute(itemId))
}
)
}
composable(
route = Screen.Detail.route,
arguments = listOf(navArgument("itemId") { type = NavType.IntType })
) { backStackEntry ->
val itemId = backStackEntry.arguments?.getInt("itemId") ?: 0
DetailScreen(itemId = itemId, onBackClick = { navController.popBackStack() })
}
}
}
// 4. 页面组件
@Composable
fun HomeScreen(onItemClick: (Int) -> Unit) {
Column(modifier = Modifier.padding(16.dp)) {
Text(text = "Home Screen", style = MaterialTheme.typography.headlineLarge)
Button(onClick = { onItemClick(123) }) { Text("Go to Detail") }
}
}
@Composable
fun DetailScreen(itemId: Int, onBackClick: () -> Unit) {
Column(modifier = Modifier.padding(16.dp)) {
Text(text = "Detail Screen - Item ID: $itemId", style = MaterialTheme.typography.headlineLarge)
Button(onClick = onBackClick) { Text("Back to Home") }
}
}
七、总结
Jetpack Compose 凭借声明式编程、简洁的 Kotlin API、高效的重组机制,大幅提升了 Android UI 开发效率。核心优势包括:
- 代码简洁:无需 XML,UI 逻辑与业务逻辑统一在 Kotlin 代码中;
- 响应式更新:基于状态驱动 UI,自动处理重组;
- 组件复用:可组合函数易于复用和扩展;
- 丰富的生态:与 Jetpack 其他组件(Navigation、ViewModel、Room)无缝集成;
- 实时预览:预览功能加速开发调试。
掌握 Compose 的核心概念(可组合函数、状态、重组)和布局系统,结合状态管理和动画等高级特性,可构建出高性能、现代化的 Android 界面。