JetPack Compose组件全解析(二)
上一篇我们聊了 Compose 中最基础的 8 个核心组件,这一篇将聚焦「布局容器、表单交互、页面结构」类高频组件 —— 从线性布局的 Row/Column,到页面骨架 Scaffold,再到表单常用的 Switch、Slider。
上一篇我们聊了 Compose 中最基础的 8 个核心组件,这一篇将聚焦「布局容器、表单交互、页面结构」类高频组件 —— 从线性布局的 Row/Column,到页面骨架 Scaffold,再到表单常用的 Switch、Slider。
Card
Card是一个 Material Design 风格的卡片容器组件。它通常带有圆角、阴影和边框,用于在界面上展示一块独立的、有层次感的内容区域,比如信息卡片、列表项等。
Card(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp), // 修饰卡片,如大小、边距、点击事件等
shape = RoundedCornerShape(8.dp), // 定义卡片的形状
colors = CardDefaults.cardColors(
containerColor = Color.White
), // 设置卡片的颜色(背景色、内容色等)
elevation = CardDefaults.cardElevation(
defaultElevation = 4.dp
), // 控制卡片的阴影高度,实现层次感
border = BorderStroke(1.dp, Color.LightGray), // 为卡片添加边框
content = {
Text(
text = "这是一个卡片示例"
)
} // 卡片内部的内容,默认为Column布局
)
Column/Row
Column是一个纵向线性布局容器,它会将其所有子组件按照垂直方向依次排列。你可以把它理解为一个垂直的 “容器”,里面的元素从上到下排成一列。
Column(
modifier = Modifier
.fillMaxWidth() //
.padding(16.dp), // modifier修饰整个 Column 布局
verticalArrangement = Arrangement.Top, // 子组件在垂直方向上的排列方式
horizontalAlignment = Alignment.CenterHorizontally, // 子组件在水平方向上的对齐方式
content = {
Text("顶部文本") // 第一个子组件
Text("中间文本") // 第二个子组件
Text("底部文本") // 第三个子组件
} // Column 的内容区域
)
Row是一个横向线性布局容器,它会将其所有子组件按照水平方向依次排列。你可以把它理解为一个水平的 “容器”,里面的元素从左到右排成一行。
Row(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp), // 修饰整个 Row 布局
horizontalArrangement = Arrangement.SpaceBetween, // 子组件在水平方向上的排列方式
verticalAlignment = Alignment.CenterVertically, // 子组件在垂直方向上的对齐方式
content = {
Text("左侧文本") // 第一个子组件
Text("中间文本") // 第二个子组件
Text("右侧文本") // 第三个子组件
} // Row 的内容区域
)
Box
Box是一个单一容器布局,它主要用于容纳一个或多个子组件。与 Row 和 Column 不同,Box 没有固定的排列方向,其子组件默认会堆叠在一起。你可以通过对齐方式来精确控制子组件在 Box 内的位置。
Box 类似于 Android 传统 View 体系中的 FrameLayout,非常适合实现组件的叠加效果,例如在一张图片上叠加文字或图标。
Box(
modifier = Modifier
.size(200.dp)
.background(Color.LightGray)
.padding(16.dp), // 修饰整个 Box 布局
contentAlignment = Alignment.Center, // 定义所有子组件在 Box 内的对齐方式
propagateMinConstraints = false, // 是否将 Box 的最小约束传递给子组件
content = {
// 第一个子组件(底层)
Image(
painter = painterResource(id = R.drawable.ic_launcher_foreground),
contentDescription = "背景图片",
modifier = Modifier.matchParentSize() // 让图片大小与 Box 一致
)
// 第二个子组件(上层,会叠加在图片上)
Text(
text = "叠加的文本",
color = Color.White,
style = MaterialTheme.typography.titleLarge
)
} // Box 的内容区域
)
Scaffold
Scaffold是一个页面级别的布局容器,它为 Material Design 风格的应用提供了一个标准的页面结构框架。它预先定义了放置顶部导航栏(TopAppBar)、底部导航栏(BottomAppBar)、悬浮按钮(FloatingActionButton)和内容区域的位置,能够快速搭建出符合设计规范的页面。
Scaffold(
modifier = Modifier.fillMaxSize(),
topBar = {
TopAppBar(
title = { Text("我的页面") }, // 标题
navigationIcon = { IconButton(onClick = { /* 打开抽屉/返回 */ }) { Icon(Icons.Default.Menu, contentDescription = "菜单") } }, // 左侧图标
actions = { IconButton(onClick = { /* 搜索 */ }) { Icon(Icons.Default.Search, contentDescription = "搜索") } } // 右侧图标
)
}, // 顶部导航栏
bottomBar = {
BottomAppBar {
IconButton(onClick = { /* 首页 */ }) { Icon(Icons.Default.Home, contentDescription = "首页") }
IconButton(onClick = { /* 我的 */ }) { Icon(Icons.Default.Person, contentDescription = "我的") }
}
}, // 底部导航栏
floatingActionButton = {
FloatingActionButton(onClick = { /* 执行主要操作,如添加 */ }) {
Icon(Icons.Default.Add, contentDescription = "添加")
}
}, // 悬浮按钮
floatingActionButtonPosition = FabPosition.End, // 悬浮按钮的位置
containerColor = MaterialTheme.colorScheme.background, // 内容区域的背景颜色
// 注意:content lambda 接收一个 PaddingValues 参数,它代表了内边距,用于防止内容被 topBar 或 bottomBar 遮挡
content = { innerPadding ->
LazyColumn(
modifier = Modifier.padding(innerPadding), // 应用内边距
contentPadding = PaddingValues(16.dp)
) {
items(20) { index ->
Text(text = "列表项 $index", modifier = Modifier.padding(vertical = 8.dp))
}
}
} // 页面的主要内容区域
)
Switch
Switch是一个双态切换组件,用于在 “开启” 和 “关闭” 状态之间进行切换。它是表单中常见的交互元素,通常用于控制某个功能的启用或禁用,例如 “接收通知”、“夜间模式” 等。
同时还是是一个有状态组件,这意味着它需要你提供一个 checked 状态来控制其当前表现,并通过 onCheckedChange 回调来更新这个状态。
// by 是一个委托属性,让我们可以像使用普通变量一样读写状态
var isSwitchChecked by remember { mutableStateOf(false) }
Switch(
checked = isSwitchChecked, // 控制 Switch 当前是“开启”还是“关闭”
onCheckedChange = { isSwitchChecked = it }, // 当用户点击 Switch 时触发的回调
modifier = Modifier.padding(16.dp),
thumbContent = if (isSwitchChecked) {
{
Icon(
imageVector = Icons.Filled.Check,
contentDescription = null,
modifier = Modifier.size(SwitchDefaults.IconSize)
)
}
} else {
null // 未选中时不显示内容
}, // 自定义 Switch 滑块内的内容
enabled = true, // 控制 Switch 是否可用
colors = SwitchDefaults.colors(
checkedThumbColor = Color.White, // 选中时滑块颜色
checkedTrackColor = Color(0xFF6200EE), // 选中时轨道颜色
checkedIconColor = Color(0xFF6200EE), // 选中时图标颜色(如果有 thumbContent)
uncheckedThumbColor = Color.Gray, // 未选中时滑块颜色
uncheckedTrackColor = Color.LightGray, // 未选中时轨道颜色
disabledCheckedThumbColor = Color.DarkGray, // 禁用且选中时滑块颜色
// ... 其他颜色属性
) // 自定义 Switch 的颜色
)
Slider
Slider是一个滑动选择器组件,用于让用户从一个连续的数值范围内选择一个值。常见的应用场景包括调节音量、亮度、进度条,或者设置价格、评分等。
在 Compose Material3 中,Slider 的状态管理通过 SliderState 来实现,这使得状态控制更加集中和灵活。
val sliderState = rememberSliderState(
initialValue = 30f, // 初始值
valueRange = 0f..100f, // 数值范围
steps = SliderDefaults.steps(
step = 10f, // 步长,每次滑动增加或减少 10
)
) // 创建和管理 Slider 的状态
Slider(
state = sliderState, // 控制 Slider 的所有状态
modifier = Modifier
.fillMaxWidth()
.padding(16.dp),
enabled = true, // 控制 Slider 是否可用
colors = SliderDefaults.colors(
activeTrackColor = Color(0xFF6200EE), // 已选中部分轨道颜色
inactiveTrackColor = Color.LightGray, // 未选中部分轨道颜色
thumbColor = Color(0xFF6200EE), // 滑块颜色
activeTickColor = Color.White, // 选中的刻度颜色(当有 steps 时)
), // 自定义 Slider 的颜色
interactionSource = remember { MutableInteractionSource() }, // 用于观察和自定义组件的交互状态(如按压、聚焦)
thumb = {
SliderDefaults.Thumb(
interactionSource = interactionSource,
colors = SliderDefaults.colors(thumbColor = Color(0xFF6200EE)),
enabled = enabled
)
}, // 自定义滑块的外观
track = { sliderState ->
SliderDefaults.Track(
colors = SliderDefaults.colors(
activeTrackColor = Color(0xFF6200EE),
inactiveTrackColor = Color.LightGray
),
enabled = enabled,
sliderState = sliderState
)
} // 自定义轨道的外观
)
Text(text = "当前值: ${sliderState.value.toInt()}")
TabRow&Tab
TabRow 是一个标签栏容器组件,用于承载多个 Tab 组件,形成一个可切换的标签导航栏。它负责管理标签的布局、选中状态的视觉反馈(如指示器、颜色变化),以及底部的分割线样式。通常位于页面顶部,与 Tab 组件配合使用,实现内容的分页切换(如 “推荐”“热点”“视频” 等标签页)。
Tab 是单个标签组件,对应 TabRow 中的一个可切换选项。它负责展示标签的内容(文本、图标),并通过 selected 属性响应选中状态,onClick 事件触发标签切换。Tab 不能单独使用,必须嵌套在 TabRow 的 tabs lambda 中。
var selectedTabIndex by remember { mutableStateOf(0) } // 状态管理:当前选中的标签索引
TabRow(
selectedTabIndex = selectedTabIndex, // 当前选中的标签索引
modifier = Modifier.fillMaxWidth(),
containerColor = Color.White, // TabRow 的背景颜色
contentColor = Color.Blue, // 选中标签的内容颜色(文本/图标颜色)
indicator = { tabPositions ->
// TabRowDefaults.SecondaryIndicator:默认的次级指示器样式
TabRowDefaults.SecondaryIndicator(
// 指示器偏移:跟随选中的标签位置
modifier = Modifier.tabIndicatorOffset(tabPositions[selectedTabIndex]),
color = Color.Blue, // 指示器颜色
height = 3.dp // 指示器高度
)
}, // 选中标签的指示器(下划线)样式
divider = {
HorizontalDivider(
color = Color.LightGray, // 分割线颜色
thickness = 1.dp // 分割线厚度
)
}, // TabRow 底部的分割线
tabs = {
Tab(
selected = selectedTabIndex == 0,
onClick = { selectedTabIndex = 0 },
text = { Text("推荐") },
icon = { Icon(Icons.Default.Star, contentDescription = null) }
)
Tab(
selected = selectedTabIndex == 1,
onClick = { selectedTabIndex = 1 },
text = { Text("热点") },
icon = { Icon(Icons.Default.Fire, contentDescription = null) }
)
Tab(
selected = selectedTabIndex == 2,
onClick = { selectedTabIndex = 2 },
text = { Text("视频") },
icon = { Icon(Icons.Default.VideoLibrary, contentDescription = null) }
)
} // TabRow 的子组件(必须是 Tab 组件集合
)
更多推荐




所有评论(0)