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 开发道路上的得力助手。

下一篇文章见。

相关推荐
LDyun_2 天前
.2026主流云手机测评,8款机型高压挂机实测
ios·智能手机·安卓·玩游戏
LDyun_3 天前
2026暑期云手机选型指南:从稳定性、成本到风控六大核心评判维度
arm开发·ios·智能手机·安卓·玩游戏
青枣八神4 天前
Expo如何只通过数据线连接手机的Expo go
react native·智能手机·安卓
Roki Zhang4 天前
自开发网盘APP使用说明
安卓·个人开发·网盘
雁鸣零落4 天前
浏览器扩展 CaptionGo,在网页视频上显示双语字幕,支持 PC 和手机端使用
android·chrome·edge·firefox·安卓
阿拉斯攀登7 天前
无人售货柜MQTT客户端工业级配置:心跳、遗嘱、重连、QoS适配实战
嵌入式硬件·mqtt·安卓·零售·无人售货柜·无人售货机
阿拉斯攀登7 天前
无人售货柜设备开机自动注册逻辑:唯一标识绑定、防重复、批量铺货适配
嵌入式硬件·安卓·零售·安卓驱动·无人售货柜·无人售货机
杨江8 天前
安卓app如何做自动升级
安卓
狂热开发者8 天前
用 Typeoff 把会后口述整理成 Markdown 决策记录
人工智能·windows·macos·ios·安卓
超级数据查看器13 天前
超级数据查看器 v10.0 发布
java·大数据·数据库·sqlite·安卓