第六章:UI 组件与 Material3 主题
Material3 是 Android 最新设计语言,Compose 原生支持,主题配置更简单。
6.1 主题配置
kotlin
// Theme.kt
@Composable
fun MyFirstComposeTheme(
darkTheme: Boolean = isSystemInDarkTheme(),
dynamicColor: Boolean = true,
content: @Composable () -> Unit,
) {
val colorScheme = when {
dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
val context = LocalContext.current
if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
}
darkTheme -> DarkColorScheme
else -> LightColorScheme
}
MaterialTheme(
colorScheme = colorScheme,
typography = Typography,
content = content,
)
}
主题特点:
dynamicColor--- Android 12+ 支持从壁纸提取颜色darkTheme--- 自动跟随系统深色模式colorScheme--- Material3 颜色体系(primary/secondary/tertiary)
6.2 颜色定义
kotlin
// Color.kt
val Purple80 = Color(0xFFD0BCFF)
val PurpleGrey80 = Color(0xFFCCC2DC)
val Pink80 = Color(0xFFEFB8C8)
val Purple40 = Color(0xFF6650a4)
val PurpleGrey40 = Color(0xFF625b71)
val Pink40 = Color(0xFF7D5260)
| 颜色角色 | 浅色模式 | 深色模式 |
|---|---|---|
| primary | Purple40 | Purple80 |
| secondary | PurpleGrey40 | PurpleGrey80 |
| tertiary | Pink40 | Pink80 |
6.3 通用组件:ArticleItem
列表卡片组件:
kotlin
@Composable
fun ArticleItem(
title: String,
description: String?,
thumbnail: String?,
onClick: () -> Unit,
) {
Card(
modifier = Modifier
.fillMaxWidth()
.padding(12.dp)
.clickable(onClick = onClick),
) {
Column {
ArticleImage(
imageUrl = thumbnail.orEmpty(),
contentDescription = title,
modifier = Modifier
.fillMaxWidth()
.height(180.dp),
)
Text(text = title, fontWeight = FontWeight.Bold)
Text(text = description ?: "暂无描述")
}
}
}
Card 特点:
- 带圆角和阴影的容器
- modifier 配置点击事件
- 内部 Column 竖向排列子组件
6.4 图片组件:ArticleImage
预览模式下显示占位图,运行时加载网络图片:
kotlin
@Composable
fun ArticleImage(
imageUrl: String,
modifier: Modifier = Modifier,
contentDescription: String? = null,
) {
if (LocalInspectionMode.current) {
// Preview 模式:显示占位图,不发网络请求
Box(
modifier = modifier.background(MaterialTheme.colorScheme.surfaceVariant),
contentAlignment = Alignment.Center,
) {
Icon(Icons.Default.Image, contentDescription = contentDescription)
}
} else {
// 运行时:使用 Coil 加载网络图片
AsyncImage(
model = imageUrl,
contentDescription = contentDescription,
modifier = modifier,
contentScale = ContentScale.Crop,
)
}
}
LocalInspectionMode:
- Composable 在 Android Studio Preview 时为 true
- 用于区分预览环境与真实运行环境
6.5 轮播图组件:BannerView
使用 HorizontalPager 实现自动轮播:
kotlin
@Composable
fun BannerView(images: List<String>) {
if (images.isEmpty()) return
val pagerState = rememberPagerState(pageCount = { images.size })
LaunchedEffect(Unit) {
while (true) {
delay(3000)
val nextPage = (pagerState.currentPage + 1) % images.size
pagerState.animateScrollToPage(nextPage)
}
}
Box {
HorizontalPager(state = pagerState, modifier = Modifier.height(200.dp)) { page ->
AsyncImage(model = images[page], contentDescription = null)
}
// 底部指示器
Row(modifier = Modifier.align(Alignment.BottomCenter)) {
repeat(images.size) { index ->
Box(modifier = Modifier
.size(8.dp)
.clip(CircleShape)
.background(if (pagerState.currentPage == index) Color.White else Color.Gray))
}
}
}
}
关键点:
rememberPagerState保存分页状态LaunchedEffect启动协程控制自动轮播- 页面指示器根据当前页切换颜色
6.6 头像组件:ProfileAvatar
kotlin
@Composable
fun ProfileAvatar(avatarUrl: String, modifier: Modifier = Modifier) {
if (LocalInspectionMode.current) {
Box(
modifier = modifier.clip(CircleShape).background(primary.copy(alpha = 0.15f)),
contentAlignment = Alignment.Center,
) {
Icon(Icons.Default.Person, modifier = Modifier.size(48.dp))
}
} else {
AsyncImage(
model = avatarUrl,
contentDescription = "用户头像",
modifier = modifier.clip(CircleShape),
contentScale = ContentScale.Crop,
)
}
}
6.7 主题使用示例
kotlin
@Composable
fun DetailArticleBody(article: ArticleBean) {
Column(modifier = Modifier.padding(16.dp)) {
Text(
text = article.title,
style = MaterialTheme.typography.headlineSmall, // 使用主题字体
fontWeight = FontWeight.Bold,
)
Text(
text = "¥${"%.2f".format(article.price)}",
color = MaterialTheme.colorScheme.primary, // 使用主题颜色
fontSize = 22.sp,
)
Card(
colors = CardDefaults.cardColors(
containerColor = MaterialTheme.colorScheme.surfaceContainerHigh,
),
) { /* ... */ }
}
}
6.8 总结
- Material3 主题支持动态颜色(Android 12+)
- LocalInspectionMode 区分预览/运行模式
- Coil 异步加载网络图片
- HorizontalPager 实现轮播
- Card 提供圆角阴影容器
- 颜色/字体均通过 MaterialTheme 主题统一管理