Android Compose UI 详解:组件、修饰符与布局注意事项
Jetpack Compose 是 Android 官方的声明式 UI 框架,基于 Kotlin 构建,通过可组合函数(@Composable
)描述 UI。以下是其核心组件、修饰符用法及布局注意事项的详细说明:
一、核心 UI 组件(Composables)
1. 基础组件
用于展示文本、图片、按钮等基础元素。
组件 | 作用 | 常用参数 | 示例 |
---|---|---|---|
Text |
显示文本 | text (内容)、fontSize 、color 、fontWeight 、maxLines |
kotlin Text( text = "Hello Compose", fontSize = 18.sp, color = Color.Blue, fontWeight = FontWeight.Bold ) |
Image |
显示图片 | painter (资源)、contentDescription (无障碍描述)、contentScale (缩放模式) |
kotlin Image( painter = painterResource(id = R.drawable.ic_logo), contentDescription = "App Logo", contentScale = ContentScale.Fit ) |
Button |
可点击按钮 | onClick (点击事件)、modifier 、colors (颜色)、shape (形状) |
kotlin Button( onClick = { /* 点击逻辑 */ }, colors = ButtonDefaults.buttonColors(containerColor = Color.Green) ) { Text("Click Me") } |
Icon |
显示系统图标 | imageVector (矢量图标)、contentDescription 、tint (色调) |
kotlin Icon( imageVector = Icons.Default.Favorite, contentDescription = "Like", tint = Color.Red ) |
TextField |
文本输入框 | value (输入值)、onValueChange (值变化回调)、label (标签)、placeholder (占位符) |
kotlin var text by remember { mutableStateOf("") } TextField( value = text, onValueChange = { text = it }, label = { Text("Enter text") } ) |
2. 布局容器
用于组织多个组件的排列方式,类似传统布局的 LinearLayout
或 FrameLayout
。
容器 | 作用 | 关键参数 | 示例 |
---|---|---|---|
Column |
垂直排列子组件 | horizontalAlignment (水平对齐)、verticalArrangement (垂直间距)、modifier |
kotlin Column( horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.spacedBy(8.dp) ) { Text("First") Text("Second") } |
Row |
水平排列子组件 | verticalAlignment (垂直对齐)、horizontalArrangement (水平间距) |
kotlin Row( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.SpaceBetween ) { Text("Left") Text("Right") } |
Box |
层叠排列子组件(类似 FrameLayout ) |
contentAlignment (子组件对齐方式) |
kotlin Box(contentAlignment = Alignment.Center) { Image(...) // 底层 Text("Overlay") // 叠加在图片上 } |
LazyColumn |
高效滚动列表(仅渲染可见项) | content (列表项)、modifier |
kotlin LazyColumn { items(100) { index -> Text("Item $index") } } |
LazyRow |
水平滚动列表 | 同 LazyColumn ,方向为水平 |
kotlin LazyRow { items(50) { Text("Item $it") } } |
ConstraintLayout |
复杂约束布局 | 通过 createRefs() 定义约束关系 |
kotlin ConstraintLayout { val (text, button) = createRefs() Text("Hello", modifier = Modifier.constrainAs(text) { top.linkTo(parent.top) }) Button( modifier = Modifier.constrainAs(button) { top.linkTo(text.bottom) } ) { Text("Button") } } |
3. 交互组件
用于响应用户操作(点击、滑动等)。
组件 | 作用 | 示例 |
---|---|---|
Clickable |
使任意组件可点击 | kotlin Text("Click me") .clickable { /* 点击逻辑 */ } |
Checkbox |
复选框 | kotlin var checked by remember { mutableStateOf(false) } Checkbox( checked = checked, onCheckedChange = { checked = it } ) |
RadioButton |
单选按钮(需配合 RadioGroup 逻辑) |
kotlin var selectedOption by remember { mutableStateOf("A") } RadioButton( selected = selectedOption == "A", onClick = { selectedOption = "A" } ) |
Switch |
开关控件 | kotlin var enabled by remember { mutableStateOf(false) } Switch( checked = enabled, onCheckedChange = { enabled = it } ) |
Slider |
滑动条(选择数值) | kotlin var progress by remember { mutableStateOf(0.5f) } Slider( value = progress, onValueChange = { progress = it } ) |
4. 容器组件
用于分组或装饰子组件。
组件 | 作用 | 示例 |
---|---|---|
Card |
带阴影和圆角的卡片容器 | kotlin Card( elevation = 4.dp, shape = RoundedCornerShape(8.dp), modifier = Modifier.padding(8.dp) ) { Column { Text("Card Title") } } |
Surface |
基础容器,可设置背景、边框等 | kotlin Surface( color = Color.LightGray, modifier = Modifier.padding(8.dp) ) { Text("Content") } |
ScrollState + Scrollable |
自定义滚动容器(替代 ScrollView ) |
kotlin val scrollState = rememberScrollState() Column( modifier = Modifier.verticalScroll(scrollState) ) { // 长内容 } |
二、修饰符(Modifier)详解
修饰符(Modifier
)用于修改组件的外观和行为,通过链式调用组合多个效果。常用修饰符分类如下:
1. 尺寸与布局
控制组件的大小、位置和约束。
修饰符 | 作用 | 示例 |
---|---|---|
size(width, height) |
固定宽高 | Modifier.size(100.dp, 50.dp) |
size(size) |
宽高相等(正方形) | Modifier.size(50.dp) |
width(width) / height(height) |
单独设置宽/高 | Modifier.width(200.dp) |
fillMaxSize() |
占满父容器的宽和高 | Modifier.fillMaxSize() |
fillMaxWidth() / fillMaxHeight() |
占满父容器的宽/高 | Modifier.fillMaxWidth(0.8f) (占 80% 宽度) |
wrapContentSize() |
尺寸适应内容 | Modifier.wrapContentSize() |
minimumSize() / maximumSize() |
最小/最大尺寸限制 | Modifier.minimumSize(50.dp) |
2. 间距与边距
控制组件的内边距和外边距。
修饰符 | 作用 | 示例 |
---|---|---|
padding(all) |
四周统一内边距 | Modifier.padding(16.dp) |
padding(horizontal, vertical) |
水平和垂直内边距 | Modifier.padding(8.dp, 16.dp) |
padding(start, top, end, bottom) |
单独设置四边内边距 | Modifier.padding(4.dp, 8.dp, 4.dp, 8.dp) |
padding(insets) |
基于系统Insets(如状态栏)的内边距 | Modifier.padding(WindowInsets.statusBars.asPaddingValues()) |
margin() |
外边距(同 padding ,但作用于组件外部) |
Modifier.margin(8.dp) |
3. 背景与边框
设置组件的背景色、形状和边框。
修饰符 | 作用 | 示例 |
---|---|---|
background(color, shape) |
背景色和形状 | Modifier.background(Color.Blue, RoundedCornerShape(8.dp)) |
border(width, color, shape) |
边框 | Modifier.border(2.dp, Color.Red, CircleShape) |
clip(shape) |
裁剪组件为指定形状 | Modifier.clip(RoundedCornerShape(4.dp)) |
4. 交互与行为
控制组件的交互能力(点击、焦点等)。
修饰符 | 作用 | 示例 |
---|---|---|
clickable(onClick, enabled) |
使组件可点击 | Modifier.clickable { /* 逻辑 */ }.enabled(false) (禁用点击) |
focusable() |
允许组件获取焦点(用于键盘导航) | Modifier.focusable() |
scrollable(state, orientation) |
使组件可滚动 | Modifier.scrollable(rememberScrollState(), Orientation.Vertical) |
draggable(state) |
使组件可拖拽 | kotlin val offset = remember { mutableStateOf(Offset.Zero) } Box( modifier = Modifier .offset { IntOffset(offset.value.x.roundToInt(), offset.value.y.roundToInt()) .draggable( onDrag = { delta -> offset.value += delta } ) } ) |
5. 其他常用修饰符
修饰符 | 作用 | 示例 |
---|---|---|
align(alignment) |
在父容器中对齐(仅在 Box /Column /Row 中生效) |
Modifier.align(Alignment.CenterEnd) |
weight(weight) |
在 Column /Row 中分配剩余空间 |
Modifier.weight(1f) (占 1 份权重) |
alpha(alpha) |
透明度(0f 全透明,1f 不透明) | Modifier.alpha(0.5f) |
rotation(degrees) |
旋转组件 | Modifier.rotation(45f) |
scale(scaleX, scaleY) |
缩放组件 | Modifier.scale(1.5f) |
testTag(tag) |
用于 UI 测试的标记 | Modifier.testTag("submit_button") |
三、布局 UI 时的注意事项
1. 性能优化
-
避免过度重组:
-
将复杂 UI 拆分为小型可组合函数,减少状态变化时的重组范围。
-
用
remember
缓存计算结果或对象,避免重复创建:kotlin// 缓存点击事件(避免每次重组创建新 lambda) val onButtonClick = remember { { /* 逻辑 */ } } Button(onClick = onButtonClick) { ... }
-
避免在
modifier
中创建匿名对象(如Modifier.clickable { ... }
中的 lambda 会被频繁重建,复杂逻辑需用remember
缓存)。
-
-
列表优化:
-
长列表必须使用
LazyColumn
/LazyRow
,而非Column
+Scrollable
(前者仅渲染可见项,后者会加载所有项)。 -
为
LazyColumn
的items
提供稳定的key
,避免不必要的项重建:kotlinLazyColumn { items(users, key = { it.id }) { user -> // 用唯一 ID 作为 key UserItem(user) } }
-
-
图片优化:
-
网络图片使用
Coil
库(rememberAsyncImagePainter
),支持缓存和占位符:kotlinImage( painter = rememberAsyncImagePainter( model = "https://example.com/image.jpg", placeholder = painterResource(id = R.drawable.placeholder) ), contentDescription = null )
-
本地图片避免使用过大分辨率,通过
contentScale
适配容器尺寸。
-
2. 布局结构合理性
-
减少嵌套层级:
- 避免多层
Box
/Column
嵌套(如Box { Box { Column { ... } } }
),会增加布局计算耗时。 - 优先使用
ConstraintLayout
实现复杂布局,减少嵌套。
- 避免多层
-
权重分配谨慎使用:
weight
修饰符会强制子组件占据剩余空间,过度使用可能导致布局计算复杂。- 在
LazyColumn
中避免使用weight
(会破坏懒加载机制)。
-
处理不同屏幕尺寸:
-
使用
dp
作为尺寸单位(自动适配不同密度屏幕)。 -
避免硬编码尺寸,优先用
fillMaxWidth
/wrapContentSize
自适应。 -
对大屏幕(如平板),可通过
WindowSizeClass
动态调整布局:kotlinval windowSizeClass = calculateWindowSizeClass(context) if (windowSizeClass.widthSizeClass > WindowWidthSizeClass.Compact) { // 平板:水平布局 Row { ... } } else { // 手机:垂直布局 Column { ... } }
-
3. 无障碍支持
-
为所有交互组件和图片添加
contentDescription
,方便屏幕阅读器识别:kotlinImage( painter = ..., contentDescription = "用户头像" // 必须提供,除非是纯装饰性图片(设为 null 并添加 .semantics { isDecoration = true }) )
-
使用
Semantics
修饰符增强无障碍信息:kotlinButton(onClick = {}) { Text("提交") }.semantics { contentDescription = "确认表单提交按钮" }
4. 主题与样式统一
-
所有组件样式(颜色、字体、形状)应基于
MaterialTheme
,避免硬编码:kotlin// 正确:使用主题颜色 Text( "Title", color = MaterialTheme.colorScheme.primary, style = MaterialTheme.typography.headlineSmall ) // 错误:硬编码颜色 Text("Title", color = Color(0xFF6200EE)) // 难以统一修改
-
通过
CompositionLocalProvider
自定义主题扩展(如自定义间距、圆角)。
5. 与传统 View 的兼容
-
在 Compose 中嵌入传统 View 时,使用
AndroidView
并注意生命周期管理:kotlinAndroidView( factory = { context -> TextView(context).apply { text = "传统 TextView" } }, update = { textView -> // 当依赖的状态变化时更新 View textView.text = newText } )
-
避免频繁在 Compose 和传统 View 间切换,可能导致性能问题。
总结
Compose 通过组件和修饰符的组合实现灵活的 UI 开发,核心是声明式思想和状态驱动。布局时需关注性能(重组、列表优化)、结构合理性(减少嵌套、适配屏幕)、无障碍支持和样式统一。熟练掌握这些细节可显著提升开发效率和应用质量。