Android 开发入门教程(第三十五篇):Compose 中的 Material Design 3 —— 构建现代化 UI 的完整组件库

引言:Material Design 与 Compose 的完美结合

Material Design 是 Google 于 2014 年推出的设计语言,旨在为跨平台设备提供统一的视觉和交互体验。经过近十年的演进,Material Design 已经发展到了第三个版本(Material Design 3,也称作 Material You)。

Material Design 3 的核心特性包括:

  • 动态配色:系统可以根据壁纸自动生成配色方案

  • 组件更新:按钮、卡片、导航栏等组件样式升级

  • 无障碍增强:更高的对比度要求,更好的触摸目标

  • 自适应布局:对不同屏幕尺寸更好的支持

Jetpack Compose 从一开始就深度整合了 Material Design。Compose 的 material3 库提供了完整的 Material Design 3 组件实现,包括颜色系统、排版、形状以及各种 UI 组件。

在本篇中,我们将系统介绍 Compose Material Design 3 的各个组件:

  • MaterialTheme 与颜色系统

  • 排版系统(Typography)

  • 形状系统(Shapes)

  • 按钮系列(Button、TextButton、OutlinedButton、IconButton)

  • 导航组件(TopAppBar、BottomNavigation、NavigationRail)

  • 容器组件(Card、Surface)

  • 数据展示组件(Badge、Chip、Switch、Slider、Checkbox、RadioButton)

  • 反馈组件(Snackbar、Dialog、ProgressIndicator)

注意:本篇假设你已经熟悉 Compose 基础。Material 3 组件在 androidx.compose.material3 包中。

一、MaterialTheme 与颜色系统

1.1 基本主题设置

kotlin

复制代码
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.lightColorScheme
import androidx.compose.material3.darkColorScheme

@Composable
fun MyAppTheme(
    darkTheme: Boolean = isSystemInDarkTheme(),
    content: @Composable () -> Unit
) {
    val colorScheme = if (darkTheme) {
        darkColorScheme(
            primary = Color(0xFFBB86FC),
            secondary = Color(0xFF03DAC6),
            tertiary = Color(0xFFFFB74D),
            background = Color(0xFF121212),
            surface = Color(0xFF1E1E1E)
        )
    } else {
        lightColorScheme(
            primary = Color(0xFF6200EE),
            secondary = Color(0xFF03DAC6),
            tertiary = Color(0xFFFF9800),
            background = Color(0xFFFFFFFF),
            surface = Color(0xFFFFFFFF)
        )
    }
    
    MaterialTheme(
        colorScheme = colorScheme,
        typography = MyTypography,
        shapes = MyShapes,
        content = content
    )
}

1.2 使用主题颜色

kotlin

复制代码
@Composable
fun ThemedComponent() {
    // 使用主题中的颜色
    Surface(
        color = MaterialTheme.colorScheme.primaryContainer,
        contentColor = MaterialTheme.colorScheme.onPrimaryContainer
    ) {
        Text(
            text = "这是一个容器",
            modifier = Modifier.padding(16.dp)
        )
    }
    
    Button(
        onClick = { },
        colors = ButtonDefaults.buttonColors(
            containerColor = MaterialTheme.colorScheme.secondary
        )
    ) {
        Text("次要按钮")
    }
}

1.3 MaterialTheme 提供的颜色

颜色角色 用途
primary 主要品牌色
onPrimary 在 primary 上方的元素颜色
primaryContainer 主要色容器
secondary 次要品牌色
onSecondary 在 secondary 上方的元素颜色
tertiary 第三品牌色
background 背景色
surface 表面色
error 错误色
surfaceVariant 表面变体色

二、排版系统

kotlin

复制代码
import androidx.compose.material3.Typography
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.sp

val MyTypography = Typography(
    displayLarge = TextStyle(
        fontFamily = FontFamily.Default,
        fontWeight = FontWeight.Bold,
        fontSize = 57.sp,
        lineHeight = 64.sp
    ),
    displayMedium = TextStyle(
        fontWeight = FontWeight.Bold,
        fontSize = 45.sp,
        lineHeight = 52.sp
    ),
    displaySmall = TextStyle(
        fontWeight = FontWeight.Bold,
        fontSize = 36.sp,
        lineHeight = 44.sp
    ),
    headlineLarge = TextStyle(
        fontWeight = FontWeight.SemiBold,
        fontSize = 32.sp,
        lineHeight = 40.sp
    ),
    headlineMedium = TextStyle(
        fontWeight = FontWeight.SemiBold,
        fontSize = 28.sp,
        lineHeight = 36.sp
    ),
    headlineSmall = TextStyle(
        fontWeight = FontWeight.SemiBold,
        fontSize = 24.sp,
        lineHeight = 32.sp
    ),
    bodyLarge = TextStyle(
        fontWeight = FontWeight.Normal,
        fontSize = 16.sp,
        lineHeight = 24.sp
    ),
    bodyMedium = TextStyle(
        fontWeight = FontWeight.Normal,
        fontSize = 14.sp,
        lineHeight = 20.sp
    ),
    bodySmall = TextStyle(
        fontWeight = FontWeight.Normal,
        fontSize = 12.sp,
        lineHeight = 16.sp
    ),
    labelLarge = TextStyle(
        fontWeight = FontWeight.Medium,
        fontSize = 14.sp,
        lineHeight = 20.sp
    ),
    labelMedium = TextStyle(
        fontWeight = FontWeight.Medium,
        fontSize = 12.sp,
        lineHeight = 16.sp
    )
)

@Composable
fun TypographyDemo() {
    Column {
        Text("Display Large", style = MaterialTheme.typography.displayLarge)
        Text("Display Medium", style = MaterialTheme.typography.displayMedium)
        Text("Display Small", style = MaterialTheme.typography.displaySmall)
        Text("Headline Large", style = MaterialTheme.typography.headlineLarge)
        Text("Body Large", style = MaterialTheme.typography.bodyLarge)
        Text("Body Medium", style = MaterialTheme.typography.bodyMedium)
        Text("Label Large", style = MaterialTheme.typography.labelLarge)
    }
}

三、形状系统

kotlin

复制代码
import androidx.compose.material3.Shapes
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.ui.unit.dp

val MyShapes = Shapes(
    extraSmall = RoundedCornerShape(4.dp),
    small = RoundedCornerShape(8.dp),
    medium = RoundedCornerShape(12.dp),
    large = RoundedCornerShape(16.dp),
    extraLarge = RoundedCornerShape(28.dp)
)

@Composable
fun ShapesDemo() {
    Column {
        Surface(
            shape = MaterialTheme.shapes.small,
            modifier = Modifier.size(80.dp),
            color = MaterialTheme.colorScheme.primary
        ) {
            // 小圆角内容
        }
        
        Surface(
            shape = MaterialTheme.shapes.medium,
            modifier = Modifier.size(80.dp),
            color = MaterialTheme.colorScheme.secondary
        ) {
            // 中圆角内容
        }
        
        Card(
            shape = MaterialTheme.shapes.large,
            modifier = Modifier.fillMaxWidth()
        ) {
            Text("大圆角卡片", modifier = Modifier.padding(16.dp))
        }
    }
}

四、按钮系列

4.1 FilledButton(填充按钮)

kotlin

复制代码
@Composable
fun FilledButtonExample() {
    Button(
        onClick = { },
        modifier = Modifier.fillMaxWidth()
    ) {
        Text("填充按钮")
    }
}

4.2 OutlinedButton(边框按钮)

kotlin

复制代码
@Composable
fun OutlinedButtonExample() {
    OutlinedButton(
        onClick = { },
        modifier = Modifier.fillMaxWidth()
    ) {
        Text("边框按钮")
    }
}

4.3 TextButton(文本按钮)

kotlin

复制代码
@Composable
fun TextButtonExample() {
    TextButton(
        onClick = { },
        modifier = Modifier.fillMaxWidth()
    ) {
        Text("文本按钮")
    }
}

4.4 IconButton(图标按钮)

kotlin

复制代码
@Composable
fun IconButtonExample() {
    IconButton(
        onClick = { }
    ) {
        Icon(Icons.Default.Favorite, contentDescription = "收藏")
    }
}

4.5 FilledTonalButton(色调按钮)

kotlin

复制代码
@Composable
fun TonalButtonExample() {
    FilledTonalButton(
        onClick = { },
        modifier = Modifier.fillMaxWidth()
    ) {
        Text("色调按钮")
    }
}

4.6 带图标按钮

kotlin

复制代码
@Composable
fun IconButtonExample() {
    Button(
        onClick = { },
        modifier = Modifier.fillMaxWidth()
    ) {
        Icon(Icons.Default.Add, contentDescription = null)
        Spacer(modifier = Modifier.width(8.dp))
        Text("添加")
    }
}

4.7 按钮状态

kotlin

复制代码
@Composable
fun ButtonStatesExample() {
    var isLoading by remember { mutableStateOf(false) }
    
    Column {
        Button(
            onClick = { },
            enabled = false,
            modifier = Modifier.fillMaxWidth()
        ) {
            Text("禁用按钮")
        }
        
        Button(
            onClick = { isLoading = !isLoading },
            modifier = Modifier.fillMaxWidth()
        ) {
            if (isLoading) {
                CircularProgressIndicator(
                    modifier = Modifier.size(24.dp),
                    color = Color.White
                )
            } else {
                Text("点击加载")
            }
        }
    }
}

五、导航组件

5.1 TopAppBar

kotlin

复制代码
@Composable
fun TopAppBarExample() {
    Scaffold(
        topBar = {
            TopAppBar(
                title = { Text("标题") },
                navigationIcon = {
                    IconButton(onClick = { }) {
                        Icon(Icons.Default.ArrowBack, contentDescription = "返回")
                    }
                },
                actions = {
                    IconButton(onClick = { }) {
                        Icon(Icons.Default.Search, contentDescription = "搜索")
                    }
                    IconButton(onClick = { }) {
                        Icon(Icons.Default.MoreVert, contentDescription = "更多")
                    }
                },
                colors = TopAppBarDefaults.topAppBarColors(
                    containerColor = MaterialTheme.colorScheme.primaryContainer,
                    titleContentColor = MaterialTheme.colorScheme.onPrimaryContainer
                )
            )
        }
    ) { paddingValues ->
        Box(modifier = Modifier.padding(paddingValues)) {
            // 内容
        }
    }
}

// 中型顶部栏
@Composable
fun CenterAlignedTopAppBarExample() {
    CenterAlignedTopAppBar(
        title = { Text("居中标题") },
        navigationIcon = {
            IconButton(onClick = { }) {
                Icon(Icons.Default.ArrowBack, null)
            }
        },
        actions = {
            IconButton(onClick = { }) {
                Icon(Icons.Default.Share, null)
            }
        }
    )
}

// 大型顶部栏
@Composable
fun LargeTopAppBarExample() {
    LargeTopAppBar(
        title = { Text("大标题") },
        navigationIcon = {
            IconButton(onClick = { }) {
                Icon(Icons.Default.Menu, null)
            }
        }
    )
}

5.2 BottomNavigation

kotlin

复制代码
@Composable
fun BottomNavigationExample() {
    val items = listOf(
        NavigationItem("首页", Icons.Default.Home),
        NavigationItem("搜索", Icons.Default.Search),
        NavigationItem("收藏", Icons.Default.Favorite),
        NavigationItem("个人", Icons.Default.Person)
    )
    var selectedIndex by remember { mutableStateOf(0) }
    
    Scaffold(
        bottomBar = {
            NavigationBar {
                items.forEachIndexed { index, item ->
                    NavigationBarItem(
                        selected = selectedIndex == index,
                        onClick = { selectedIndex = index },
                        icon = { Icon(item.icon, contentDescription = item.label) },
                        label = { Text(item.label) }
                    )
                }
            }
        }
    ) { paddingValues ->
        Box(
            modifier = Modifier
                .fillMaxSize()
                .padding(paddingValues)
        ) {
            when (selectedIndex) {
                0 -> HomeScreen()
                1 -> SearchScreen()
                2 -> FavoritesScreen()
                3 -> ProfileScreen()
            }
        }
    }
}

data class NavigationItem(val label: String, val icon: ImageVector)

kotlin

复制代码
@Composable
fun NavigationRailExample() {
    val items = listOf(
        NavigationItem("首页", Icons.Default.Home),
        NavigationItem("收藏", Icons.Default.Favorite),
        NavigationItem("个人", Icons.Default.Person)
    )
    var selectedIndex by remember { mutableStateOf(0) }
    
    Row {
        NavigationRail(
            modifier = Modifier.fillMaxHeight(),
            containerColor = MaterialTheme.colorScheme.surfaceVariant
        ) {
            items.forEachIndexed { index, item ->
                NavigationRailItem(
                    selected = selectedIndex == index,
                    onClick = { selectedIndex = index },
                    icon = { Icon(item.icon, contentDescription = item.label) },
                    label = { Text(item.label) }
                )
            }
        }
        
        Box(
            modifier = Modifier
                .fillMaxSize()
                .weight(1f)
        ) {
            when (selectedIndex) {
                0 -> HomeScreen()
                1 -> FavoritesScreen()
                2 -> ProfileScreen()
            }
        }
    }
}

六、容器组件

6.1 Card

kotlin

复制代码
@Composable
fun CardExample() {
    Card(
        modifier = Modifier
            .fillMaxWidth()
            .padding(16.dp),
        colors = CardDefaults.cardColors(
            containerColor = MaterialTheme.colorScheme.surfaceVariant
        ),
        elevation = CardDefaults.cardElevation(
            defaultElevation = 4.dp
        )
    ) {
        Column(
            modifier = Modifier.padding(16.dp)
        ) {
            Text("卡片标题", style = MaterialTheme.typography.titleLarge)
            Spacer(modifier = Modifier.height(8.dp))
            Text("卡片内容,可以包含文本、图片等元素。")
        }
    }
}

6.2 Surface

Surface 是 Material Design 的基础容器,支持背景、形状、高程等。

kotlin

复制代码
@Composable
fun SurfaceExample() {
    Surface(
        modifier = Modifier
            .fillMaxWidth()
            .padding(16.dp),
        shape = RoundedCornerShape(12.dp),
        color = MaterialTheme.colorScheme.primaryContainer,
        tonalElevation = 3.dp,
        shadowElevation = 2.dp
    ) {
        Text(
            text = "Surface 容器",
            modifier = Modifier.padding(24.dp),
            color = MaterialTheme.colorScheme.onPrimaryContainer
        )
    }
}

七、数据展示组件

7.1 Badge(徽章)

kotlin

复制代码
@Composable
fun BadgeExample() {
    var notifications by remember { mutableStateOf(5) }
    
    BadgedBox(
        badge = {
            Badge(
                containerColor = MaterialTheme.colorScheme.error,
                contentColor = Color.White
            ) {
                Text(notifications.toString())
            }
        }
    ) {
        IconButton(onClick = { notifications++ }) {
            Icon(Icons.Default.Notifications, contentDescription = "通知")
        }
    }
}

7.2 Chip(芯片)

kotlin

复制代码
@Composable
fun ChipExample() {
    val chips = listOf("Android", "Kotlin", "Compose", "Material")
    var selectedChips by remember { mutableStateOf(setOf<String>()) }
    
    Row(
        horizontalArrangement = Arrangement.spacedBy(8.dp)
    ) {
        chips.forEach { chip ->
            FilterChip(
                selected = selectedChips.contains(chip),
                onClick = {
                    selectedChips = if (selectedChips.contains(chip)) {
                        selectedChips - chip
                    } else {
                        selectedChips + chip
                    }
                },
                label = { Text(chip) }
            )
        }
    }
}

// 可关闭的芯片
@Composable
fun AssistChipExample() {
    var visible by remember { mutableStateOf(true) }
    
    if (visible) {
        AssistChip(
            onClick = { },
            label = { Text("帮助提示") },
            trailingIcon = {
                IconButton(onClick = { visible = false }) {
                    Icon(Icons.Default.Close, null, modifier = Modifier.size(16.dp))
                }
            }
        )
    }
}

7.3 Switch(开关)

kotlin

复制代码
@Composable
fun SwitchExample() {
    var checked by remember { mutableStateOf(false) }
    
    Row(
        verticalAlignment = Alignment.CenterVertically,
        horizontalArrangement = Arrangement.SpaceBetween,
        modifier = Modifier.fillMaxWidth()
    ) {
        Text("启用通知")
        Switch(
            checked = checked,
            onCheckedChange = { checked = it }
        )
    }
}

7.4 Slider(滑块)

kotlin

复制代码
@Composable
fun SliderExample() {
    var value by remember { mutableStateOf(0.5f) }
    
    Column {
        Text("音量: ${(value * 100).toInt()}%")
        Slider(
            value = value,
            onValueChange = { value = it },
            valueRange = 0f..1f,
            steps = 4  // 中间档位数
        )
    }
}

// 范围滑块
@Composable
fun RangeSliderExample() {
    var range by remember { mutableStateOf(0.2f..0.8f) }
    
    Column {
        Text("价格区间: ¥${(range.start * 100).toInt()} - ¥${(range.endInclusive * 100).toInt()}")
        RangeSlider(
            value = range,
            onValueChange = { range = it },
            valueRange = 0f..1f,
            steps = 9
        )
    }
}

7.5 Checkbox(复选框)

kotlin

复制代码
@Composable
fun CheckboxExample() {
    var checked by remember { mutableStateOf(false) }
    
    Row(
        verticalAlignment = Alignment.CenterVertically
    ) {
        Checkbox(
            checked = checked,
            onCheckedChange = { checked = it }
        )
        Text("同意服务条款")
    }
}

7.6 RadioButton(单选按钮)

kotlin

复制代码
@Composable
fun RadioButtonExample() {
    val options = listOf("选项一", "选项二", "选项三")
    var selectedOption by remember { mutableStateOf(options[0]) }
    
    Column {
        options.forEach { option ->
            Row(
                verticalAlignment = Alignment.CenterVertically
            ) {
                RadioButton(
                    selected = selectedOption == option,
                    onClick = { selectedOption = option }
                )
                Text(option, modifier = Modifier.padding(start = 8.dp))
            }
        }
    }
}

7.7 ProgressIndicator(进度指示器)

kotlin

复制代码
@Composable
fun ProgressIndicatorExample() {
    var progress by remember { mutableStateOf(0f) }
    val scope = rememberCoroutineScope()
    
    Column {
        // 圆形进度指示器
        CircularProgressIndicator()
        
        Spacer(modifier = Modifier.height(16.dp))
        
        // 带进度的圆形进度指示器
        CircularProgressIndicator(
            progress = progress,
            modifier = Modifier.size(48.dp)
        )
        
        Spacer(modifier = Modifier.height(16.dp))
        
        // 线性进度指示器
        LinearProgressIndicator(
            progress = progress,
            modifier = Modifier.fillMaxWidth()
        )
        
        Button(
            onClick = {
                scope.launch {
                    while (progress < 1f) {
                        delay(100)
                        progress += 0.01f
                    }
                }
            }
        ) {
            Text("开始加载")
        }
    }
}

八、反馈组件

8.1 Snackbar

kotlin

复制代码
@Composable
fun SnackbarExample() {
    val scaffoldState = rememberScaffoldState()
    val scope = rememberCoroutineScope()
    
    Scaffold(
        scaffoldState = scaffoldState,
        snackbarHost = { SnackbarHost(it) }
    ) { paddingValues ->
        Box(modifier = Modifier.padding(paddingValues)) {
            Button(
                onClick = {
                    scope.launch {
                        scaffoldState.snackbarHostState.showSnackbar(
                            message = "操作成功",
                            actionLabel = "撤销",
                            duration = SnackbarDuration.Short
                        )
                    }
                }
            ) {
                Text("显示 Snackbar")
            }
        }
    }
}

8.2 AlertDialog

kotlin

复制代码
@Composable
fun DialogExample() {
    var showDialog by remember { mutableStateOf(false) }
    
    Button(onClick = { showDialog = true }) {
        Text("显示对话框")
    }
    
    if (showDialog) {
        AlertDialog(
            onDismissRequest = { showDialog = false },
            title = { Text("确认操作") },
            text = { Text("确定要执行此操作吗?") },
            confirmButton = {
                TextButton(onClick = { showDialog = false }) {
                    Text("确定")
                }
            },
            dismissButton = {
                TextButton(onClick = { showDialog = false }) {
                    Text("取消")
                }
            }
        )
    }
}

九、完整实战:购物应用主页

kotlin

复制代码
@Composable
fun ShoppingHomeScreen() {
    val scaffoldState = rememberScaffoldState()
    var selectedCategory by remember { mutableStateOf("推荐") }
    val categories = listOf("推荐", "手机", "电脑", "家电", "服饰")
    
    Scaffold(
        topBar = {
            TopAppBar(
                title = { Text("商城") },
                actions = {
                    IconButton(onClick = { }) {
                        Icon(Icons.Default.Search, null)
                    }
                    IconButton(onClick = { }) {
                        BadgedBox(
                            badge = { Badge { Text("3") } }
                        ) {
                            Icon(Icons.Default.ShoppingCart, null)
                        }
                    }
                },
                colors = TopAppBarDefaults.topAppBarColors(
                    containerColor = MaterialTheme.colorScheme.primary,
                    titleContentColor = Color.White
                )
            )
        },
        bottomBar = {
            NavigationBar {
                val items = listOf(
                    "首页" to Icons.Default.Home,
                    "分类" to Icons.Default.Category,
                    "购物车" to Icons.Default.ShoppingCart,
                    "个人" to Icons.Default.Person
                )
                var selected by remember { mutableStateOf(0) }
                
                items.forEachIndexed { index, (label, icon) ->
                    NavigationBarItem(
                        selected = selected == index,
                        onClick = { selected = index },
                        icon = { Icon(icon, null) },
                        label = { Text(label) }
                    )
                }
            }
        }
    ) { paddingValues ->
        Column(
            modifier = Modifier
                .fillMaxSize()
                .padding(paddingValues)
        ) {
            // 分类标签栏
            LazyRow(
                contentPadding = PaddingValues(horizontal = 16.dp),
                horizontalArrangement = Arrangement.spacedBy(8.dp)
            ) {
                items(categories) { category ->
                    FilterChip(
                        selected = selectedCategory == category,
                        onClick = { selectedCategory = category },
                        label = { Text(category) }
                    )
                }
            }
            
            // 商品列表
            LazyVerticalGrid(
                columns = GridCells.Fixed(2),
                contentPadding = PaddingValues(16.dp),
                horizontalArrangement = Arrangement.spacedBy(12.dp),
                verticalArrangement = Arrangement.spacedBy(12.dp)
            ) {
                items(10) { index ->
                    ProductCard(
                        name = "商品 $index",
                        price = "¥${(index + 1) * 99}",
                        onAddToCart = {
                            // 添加到购物车
                        }
                    )
                }
            }
        }
    }
}

@Composable
fun ProductCard(
    name: String,
    price: String,
    onAddToCart: () -> Unit
) {
    Card(
        modifier = Modifier.fillMaxWidth(),
        elevation = CardDefaults.cardElevation(defaultElevation = 2.dp)
    ) {
        Column(
            modifier = Modifier.padding(12.dp)
        ) {
            Box(
                modifier = Modifier
                    .fillMaxWidth()
                    .aspectRatio(1f)
                    .background(
                        color = MaterialTheme.colorScheme.surfaceVariant,
                        shape = RoundedCornerShape(8.dp)
                    )
            ) {
                // 商品图片
                Icon(
                    Icons.Default.Image,
                    null,
                    modifier = Modifier.align(Alignment.Center),
                    tint = MaterialTheme.colorScheme.onSurfaceVariant
                )
            }
            
            Spacer(modifier = Modifier.height(8.dp))
            
            Text(
                text = name,
                style = MaterialTheme.typography.bodyMedium,
                maxLines = 1,
                overflow = TextOverflow.Ellipsis
            )
            
            Text(
                text = price,
                style = MaterialTheme.typography.titleMedium,
                color = MaterialTheme.colorScheme.primary
            )
            
            Spacer(modifier = Modifier.height(8.dp))
            
            Button(
                onClick = onAddToCart,
                modifier = Modifier.fillMaxWidth(),
                shape = MaterialTheme.shapes.small
            ) {
                Text("加入购物车")
            }
        }
    }
}

十、Material Design 3 组件速查表

组件 用途 主要参数
Button 主要操作按钮 onClick, enabled, colors
OutlinedButton 次要操作 onClick, colors
TextButton 低强调操作 onClick
IconButton 图标按钮 onClick
FloatingActionButton 主要悬浮操作 onClick
TopAppBar 顶部导航栏 title, navigationIcon, actions
BottomNavigation 底部导航 items, selectedIndex
NavigationRail 侧边导航(大屏幕) items, selectedIndex
Card 容器卡片 colors, elevation
Surface 基础容器 color, shape, elevation
Badge 徽章/角标 containerColor
Chip 标签/筛选 onClick, label, selected
Switch 开关控制 checked, onCheckedChange
Slider 滑动选择 value, onValueChange
Checkbox 多选 checked, onCheckedChange
RadioButton 单选 selected, onClick
CircularProgressIndicator 圆形进度 progress
LinearProgressIndicator 线性进度 progress
Snackbar 底部提示 action, duration
AlertDialog 对话框 title, text, confirmButton
DropdownMenu 下拉菜单 expanded, onDismissRequest

练习题

  1. 题一:创建一个完整的应用主题,包含深色和浅色模式切换功能。

  2. 题二 :使用 CardButtonSwitch 等组件实现一个设备控制面板。

  3. 题三:实现一个带有底部导航栏的应用,包含三个页面:首页、收藏、个人中心。

  4. 题四 :使用 RangeSlider 实现商品价格筛选功能。

  5. 题五:创建一组筛选芯片(Chip),支持单选和多选模式。

写在最后

Material Design 3 是 Compose 的官方设计语言,掌握 Material 3 组件库是开发现代化 Android 应用的必备技能。本系列已经发布了三十五篇教程,覆盖了从环境搭建到高级组件的方方面面。

希望这个系列能成为你在 Android 开发道路上的得力助手。

下一篇文章见。

相关推荐
UnicornDev6 小时前
Android 开发入门教程(第三十四篇):Compose 中的图像与图标 —— 从基础显示到性能优化
安卓
上天_去_做颗惺星 EVE_BLUE4 天前
Ubuntu Android 虚拟机安装使用教程
android·linux·测试工具·ubuntu·安卓
我命由我123454 天前
Android 开发问题:Could not find com.github.PicnicSupermarket:FingerPaintView:1.2.
android·github·android studio·安卓·android jetpack·android-studio·android runtime
Andy Wee5 天前
红米K40 BootLoader 解锁完整教程(避坑版)
安卓
vensli6 天前
消息跨端架构演进:基于 C++ 的多端一致性研发框架实践
java·人工智能·软件工程·安卓
vensli7 天前
来自 Android14 的“酷炫惊喜动画”——记录一次安卓动画缓存问题的排查过程
安卓
会Tk矩阵群控的小木11 天前
rcs安卓增强短信群发系统搭建与API集成实战教程
矩阵·新媒体运营·安卓·个人开发·tk
Java小学生丶11 天前
记录一下我的 Gradle 开发环境配置过程
android·java·gradle·maven·安卓
therese_1008615 天前
客户端设计(下):场景流派与实战设计方式
架构·安卓·鸿蒙