在 Jetpack Compose 中,主题和样式是通过 MaterialTheme
和自定义样式系统实现的。下面我将通过实战示例展示如何自定义和应用主题样式。
1. 基础主题设置
定义颜色方案
// 自定义颜色方案
val MyAppColors = lightColors(
primary = Color(0xFF6200EE),
primaryVariant = Color(0xFF3700B3),
secondary = Color(0xFF03DAC6),
secondaryVariant = Color(0xFF018786),
background = Color(0xFFFFFFFF),
surface = Color(0xFFFFFFFF),
error = Color(0xFFB00020),
onPrimary = Color.White,
onSecondary = Color.Black,
onBackground = Color.Black,
onSurface = Color.Black,
onError = Color.White
)
// 深色主题颜色方案
val DarkColors = darkColors(
primary = Color(0xFFBB86FC),
primaryVariant = Color(0xFF3700B3),
secondary = Color(0xFF03DAC6),
background = Color(0xFF121212),
surface = Color(0xFF1E1E1E),
onPrimary = Color.Black,
onBackground = Color.White,
onSurface = Color.White
)
定义排版样式
val MyAppTypography = Typography(
h1 = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Light,
fontSize = 96.sp,
letterSpacing = (-1.5).sp
),
h2 = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Light,
fontSize = 60.sp,
letterSpacing = (-0.5).sp
),
body1 = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Normal,
fontSize = 16.sp,
lineHeight = 24.sp,
letterSpacing = 0.5.sp
),
button = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Medium,
fontSize = 14.sp,
letterSpacing = 1.25.sp
)
// 可以继续定义其他文本样式...
)
定义形状样式
val MyAppShapes = Shapes(
small = RoundedCornerShape(4.dp),
medium = RoundedCornerShape(8.dp),
large = RoundedCornerShape(16.dp)
)
应用主题
@Composable
fun MyAppTheme(
darkTheme: Boolean = isSystemInDarkTheme(),
content: @Composable () -> Unit
) {
val colors = if (darkTheme) DarkColors else MyAppColors
MaterialTheme(
colors = colors,
typography = MyAppTypography,
shapes = MyAppShapes,
content = content
)
}
2. 实际应用示例
在应用中使用主题
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MyAppTheme {
// 整个应用的内容
MyApp()
}
}
}
}
@Composable
fun MyApp() {
Surface(color = MaterialTheme.colors.background) {
Column(modifier = Modifier.padding(16.dp)) {
Text(
text = "标题",
style = MaterialTheme.typography.h1,
color = MaterialTheme.colors.primary
)
Spacer(modifier = Modifier.height(16.dp))
Button(onClick = { /* 点击操作 */ }) {
Text("主题按钮")
}
}
}
}
3. 高级样式技巧
创建自定义文本样式
@Composable
fun HighlightText(text: String) {
Text(
text = text,
style = MaterialTheme.typography.body1.copy(
background = MaterialTheme.colors.secondary.copy(alpha = 0.2f),
fontWeight = FontWeight.Bold
),
modifier = Modifier.padding(4.dp)
)
}
自定义按钮样式
@Composable
fun PrimaryButton(
text: String,
onClick: () -> Unit,
modifier: Modifier = Modifier
) {
Button(
onClick = onClick,
colors = ButtonDefaults.buttonColors(
backgroundColor = MaterialTheme.colors.primary,
contentColor = MaterialTheme.colors.onPrimary
),
shape = MaterialTheme.shapes.medium,
elevation = ButtonDefaults.elevation(
defaultElevation = 8.dp,
pressedElevation = 4.dp
),
modifier = modifier
) {
Text(text, style = MaterialTheme.typography.button)
}
}
动态主题切换
@Composable
fun ThemeSwitcherExample() {
var isDarkTheme by remember { mutableStateOf(false) }
MyAppTheme(darkTheme = isDarkTheme) {
Column(
modifier = Modifier
.fillMaxSize()
.padding(16.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
Switch(
checked = isDarkTheme,
onCheckedChange = { isDarkTheme = it },
colors = SwitchDefaults.colors(
checkedThumbColor = MaterialTheme.colors.secondary,
uncheckedThumbColor = MaterialTheme.colors.primary
)
)
Text(
text = if (isDarkTheme) "深色主题" else "浅色主题",
style = MaterialTheme.typography.h6
)
Spacer(modifier = Modifier.height(16.dp))
PrimaryButton(text = "示例按钮", onClick = {})
}
}
}
4. 主题扩展实践
创建扩展属性
// 定义扩展属性
val Colors.success: Color
get() = Color(0xFF4CAF50)
val Colors.warning: Color
get() = Color(0xFFFFC107)
val Colors.info: Color
get() = Color(0xFF2196F3)
// 使用扩展属性
@Composable
fun StatusIndicator(status: String) {
val color = when(status) {
"success" -> MaterialTheme.colors.success
"warning" -> MaterialTheme.colors.warning
"error" -> MaterialTheme.colors.error
else -> MaterialTheme.colors.info
}
Box(
modifier = Modifier
.size(16.dp)
.background(color, CircleShape)
)
}
创建自定义主题组件
@Composable
fun Card(
modifier: Modifier = Modifier,
content: @Composable () -> Unit
) {
Surface(
modifier = modifier,
shape = MaterialTheme.shapes.medium,
elevation = 4.dp,
color = MaterialTheme.colors.surface,
content = content
)
}
// 使用示例
@Composable
fun UserProfileCard(user: User) {
Card(modifier = Modifier.padding(8.dp)) {
Column(modifier = Modifier.padding(16.dp)) {
Text(
text = user.name,
style = MaterialTheme.typography.h6,
color = MaterialTheme.colors.onSurface
)
Spacer(modifier = Modifier.height(8.dp))
Text(
text = user.bio,
style = MaterialTheme.typography.body2
)
}
}
}
5. 响应式主题设计
@Composable
fun ResponsiveContent() {
// 根据屏幕宽度决定布局
val configuration = LocalConfiguration.current
val screenWidth = configuration.screenWidthDp.dp
val isWideScreen = screenWidth >= 600.dp
if (isWideScreen) {
Row {
// 宽屏布局
NavigationRail()
MainContent()
}
} else {
// 窄屏布局
Scaffold(
bottomBar = { BottomNavigation() }
) {
MainContent()
}
}
}
@Composable
fun NavigationRail() {
NavigationRail(
backgroundColor = MaterialTheme.colors.surface,
contentColor = MaterialTheme.colors.onSurface
) {
// 导航项...
}
}
通过以上实战示例,你可以全面掌握 Jetpack Compose 中的主题和样式应用。记住,Compose 的声明式特性使得样式重用和主题切换变得非常简单,合理组织你的主题系统可以大大提高 UI 的一致性和开发效率。