本文介绍 Compose 的布局组件和主题系统。
Compose 提供三个基础布局组件:
Row(
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Text("左侧")
Text("右侧")
}Column(
verticalArrangement = Arrangement.spacedBy(8.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
Text("第一行")
Text("第二行")
}Box(modifier = Modifier.fillMaxSize()) {
Image(...)
Text("覆盖在图片上", modifier = Modifier.align(Alignment.BottomStart))
}项目中的实际布局 (
src/main/kotlin/app/Main.kt:475-490):
Row(
Modifier.fillMaxWidth().height(48.dp)
.background(MaterialTheme.colors.background)
) {
if (treeSidebarVisible) {
Box(
Modifier.fillMaxHeight().width((contentWidthPx * treeSplitRatio).dp)
) {
CollectionTreeSidebar(
// ...
)
}
Box(
Modifier.fillMaxHeight().width(1.dp).background(dividerColor)
)
}
// 右侧请求编辑区
Box(Modifier.fillMaxSize()) {
// ...
}
}修饰符是 Compose 的核心概念,通过链式调用组合样式和行为:
Text(
text = "Hello",
modifier = Modifier
.fillMaxWidth() // 宽度撑满
.padding(16.dp) // 内边距
.background(Color.Blue) // 背景色
.clickable { /* */ } // 点击事件
)常见修饰符:
fillMaxSize()/fillMaxWidth()/fillMaxHeight()wrapContentSize()size(100.dp)padding(margin)/padding(start/end/top/bottom)background(color)clickable { }
对于长列表,必须使用 LazyColumn(仅渲染可见项):
LazyColumn {
items(list) { item ->
ListItem(item)
}
}带 key 维持状态:
items(
items = requests,
key = { it.id }
) { request ->
RequestItem(request)
}项目中的树形列表 (
src/main/kotlin/tree/CollectionTreeSidebar.kt):
LazyColumn(
state = listState,
modifier = Modifier.fillMaxSize()
) {
items(
items = tree,
key = { it.id }
) { node ->
when (node) {
is TreeItem.Collection -> CollectionItem(...)
is TreeItem.Folder -> FolderItem(...)
is TreeItem.Request -> RequestItem(...)
}
}
}Compose 默认支持 Material3:
MaterialTheme(
colorScheme = ColorScheme,
typography = Typography,
content = content
)val darkColorScheme = darkColorScheme(
primary = Color(0xFFBB86FC),
secondary = Color(0xFF03DAC6),
background = Color(0xFF121212),
// ...
)
val lightColorScheme = lightColorScheme(
primary = Color(0xFF6200EE),
secondary = Color(0xFF03DAC6),
background = Color(0xFFFFFFFF),
// ...
)var isDarkTheme by remember { mutableStateOf(true) }
MaterialTheme(
colors = if (isDarkTheme) darkColors() else lightColors()
) {
// 你的 UI
}项目中的主题切换 (
src/main/kotlin/app/Main.kt:293, 293-297):
var isDarkTheme by remember { mutableStateOf(true) }
// ...
MaterialTheme(
colors = if (isDarkTheme) darkColors() else lightColors()
) {
// 布局内容
}Material3 使用更丰富的颜色角色:
import androidx.compose.material3.*
val colorScheme = darkColorScheme(
primary = md_theme_light_primary,
onPrimary = md_theme_light_onPrimary,
primaryContainer = md_theme_light_primaryContainer,
secondary = md_theme_light_secondary,
// ...
)项目中定义的颜色 (src/main/kotlin/app/Main.kt 中的引用):
MaterialTheme(
colors = if (isDarkTheme) darkColors() else lightColors()
) {
Button(
colors = ButtonDefaults.buttonColors(
backgroundColor = MaterialTheme.colors.primary
)
) { }
}import androidx.compose.material.icons.*
Icon(
imageVector = Icons.Filled.Search,
contentDescription = "搜索"
)
Icon(
imageVector = Icons.Default.Settings,
contentDescription = "设置"
)扩展图标库(项目依赖):
implementation("org.jetbrains.compose.material:material-icons-extended:1.7.3")项目中的图标使用 (
src/main/kotlin/http/RequestPanel.kt):
IconButton(onClick = onSend) {
Icon(
imageVector = Icons.Filled.Send,
contentDescription = "发送请求"
)
}val Typography = Typography(
body1 = TextStyle(fontFamily = FontFamily.Default),
h1 = TextStyle(fontSize = 24.sp)
)
Text(
text = "标题",
style = MaterialTheme.typography.h1
)Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colors.background
) {
// 内容
}带阴影的卡片:
Card(
elevation = CardDefaults.cardElevation(defaultElevation = 4.dp)
) {
Text("卡片内容")
}项目中的分割布局实现 (src/main/kotlin/app/Main.kt:475-510):
Row(
Modifier.fillMaxWidth().height(48.dp)
.background(MaterialTheme.colors.background)
) {
if (treeSidebarVisible) {
Box(
// 左侧树:宽度比例
Modifier.fillMaxHeight()
.width((contentWidthPx * treeSplitRatio).dp)
) {
CollectionTreeSidebar(...)
}
// 分隔线
Box(
Modifier.fillMaxHeight().width(1.dp)
.background(dividerColor)
)
}
// 右侧主区域
Box(Modifier.fillMaxSize()) {
// ...
}
}控制 LazyColumn 滚动位置:
val listState = rememberLazyListState()
// 滚动到指定位置
LaunchedEffect(scrollToItem) {
listState.animateScrollToItem(index = targetIndex)
}项目中的列表状态 (
src/main/kotlin/app/Main.kt:291):
val responseListState = remember(responseScopeKey) { LazyListState() }| 组件 | 用途 |
|---|---|
Row |
水平排列 |
Column |
垂直排列 |
Box |
层叠布局 |
LazyColumn |
高性能长列表 |
Modifier |
样式与行为链 |
MaterialTheme |
Material3 主题 |
Surface / Card |
容器组件 |
本篇介绍了 Compose 布局基础,下一篇我们将学习实际项目中的 HTTP 请求处理。