一、按钮布局以及按钮点击事件
按钮是基本组件,可让用户触发已定义的操作。Jetpack Compose 提供了多种预定义的按钮样式
1.1、5种按钮样式
@Composable
fun ButtonExample() {
Column(
//让当前组件填充父容器的最大可用宽高,类似于XML 布局中的match_parent 或 fill_parent
modifier = Modifier.fillMaxSize(),
//按钮在布局中居中显示
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally)
{
//填充按钮,默认情况下,它会以纯色填充
Button(onClick = { Log.d("MyButtonActivity", "Button: ") }) {
Text("Button")
}
// 填充色调按钮,默认情况下,它会填充色调颜色
FilledTonalButton(onClick = { Log.d("MyButtonActivity", "TonalButton: ") }) {
Text("TonalButton")
}
//轮廓按钮,默认情况下,它会显示轮廓
OutlinedButton(onClick = { Log.d("MyButtonActivity", "OutlinedButton: ") }) {
Text("OutlinedButton")
}
//凸起按钮,它是一个包含阴影的填充按钮
ElevatedButton(onClick = { Log.d("MyButtonActivity", "ElevatedButton: ") }) {
Text("ElevatedButton")
}
//文本按钮,在按之前,它仅显示为文字。默认情况下,它没有实心填充或轮廓
TextButton(onClick = { Log.d("MyButtonActivity", "TextButton: ") }) {
Text("TextButton")
}
}
}
效果如下:
1.2、以Button按钮为例介绍其构造函数常用属性
//创建了一个 Button 组件
Button(
//点击按钮执行事件
onClick = { /* 点击处理逻辑 */ },
//修饰符,用于调整布局、大小等
modifier = Modifier.padding(32.dp),
// 控制是否可点击
enabled = true,
//阴影效果
elevation = ButtonDefaults.buttonElevation(
defaultElevation = 8.dp,
pressedElevation = 4.dp,
disabledElevation = 0.dp
),
// 按钮形状,圆角40
shape = RoundedCornerShape(40.dp),
// 按钮边框样式
border = BorderStroke(3.dp, Color.Blue),
// 设置按钮点击/禁用时颜色变化效果:填充色 文字颜色
// colors = ButtonDefaults.buttonColors
// (containerColor = Color.Blue, contentColor = Color.White,
// disabledContainerColor = Color.Gray, disabledContentColor = Color.White),
// 内容内边距,相当于xml的padding
contentPadding = PaddingValues(horizontal = 20.dp, vertical = 8.dp)
)
//大括号 {} 内的内容是 Button 组件的 content 参数,它定义了按钮内部显示的内容和布局
//当函数的最后一个参数是 lambda 时,可以移到括号外面
//这些组件默认会按照 水平方向(Row) 自动排列
{
Icon(Icons.Filled.Favorite, contentDescription = null)
Spacer(Modifier.size(16.dp))
Text( "提交")
}
预览效果如下:
1.3、按钮点击事件
应用:实现点击按钮模拟提交文件,延迟2秒后按钮恢复正常 。
在这个案例中,我们不需要设置太多属性
@Composable
fun ButtonExample() {
//使用 remember 和 mutableStateOf 创建了一个可观察的状态变量 isEnabled管理 UI 状态
//状态变化自动触发 UI 重组
var isEnabled: Boolean by remember { mutableStateOf(true) }
//获取一个与当前组合生命周期绑定的协程作用域,使用 rememberCoroutineScope 安全地启动协程
//delay函数需在协程中执行
val coroutineScope = rememberCoroutineScope()
//点击按钮模拟文件提交功能
fun myButtonClick() {
isEnabled = false // 点击后立即禁用点击功能
coroutineScope.launch {
delay(2000) // 延迟2秒
isEnabled = true // 恢复原始状态
}
}
//创建了一个 Button 组件
Button(
//点击按钮执行事件
onClick = { myButtonClick() },
// 控制是否可点击
enabled = isEnabled,
// 设置按钮点击/禁用时颜色变化效果:填充色 文字颜色
colors = ButtonDefaults.buttonColors
(containerColor = Color.Blue, contentColor = Color.White,
disabledContainerColor = Color.Gray, disabledContentColor = Color.White),
) { Text(if (isEnabled) "提交" else "处理中...") }
}
运行效果:点击后置灰2秒钟,后又恢复正常状态
1.4、按钮点击切换背景图
在 Jetpack Compose 中,标准 Button
组件没有直接提供设置背景图片的属性,这是设计上的有意为之——Material Design 规范中的按钮通常使用纯色或渐变背景,而不是图片背景。
如果想要实现点击按钮切换背景图,可以使用 Box
容器 + Image
模拟按钮或者通过 Button
的 content
参数嵌入图片,下面我们用第二种方法实现点击切换背景图。
@Composable
fun ButtonExample() {
//使用 remember 和 mutableStateOf 创建了一个可观察的状态变量 isSelect管理 UI 状态
//状态变化自动触发 UI 重组
var isSelect: Boolean by remember { mutableStateOf(true) }
//点击按钮切换背景图
fun myButtonClick() {
isSelect = !isSelect
}
//创建了一个 Button 组件
Button(
//点击按钮执行事件
onClick = { myButtonClick() },
// 透明背景
colors = ButtonDefaults.buttonColors(containerColor = Color.Transparent)
) {
Image(
painter = painterResource( if (isSelect) R.mipmap.clickblue else R.mipmap.clickgray),
contentDescription = null,
contentScale = ContentScale.Crop,
modifier = Modifier.fillMaxWidth()
)
}
}
二、分段按钮
2.1、单选分段按钮
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun SingleChoiceSegmentedButton() {
//使用 remember 和 mutableStateOf初始化 selectedIndex 变量,以跟踪所选按钮的索引
//状态变化自动触发 UI 重组
var selectedIndex by remember { mutableIntStateOf(0) }
//定义表示按钮标签的 options 列表
val options = listOf("日", "周", "月")
//SingleChoiceSegmentedButtonRow 仅允许选择一个按钮
SingleChoiceSegmentedButtonRow {
//在 forEachIndexed 循环内,为每个选项创建一个 SegmentedButton
options.forEachIndexed { index, label ->
SegmentedButton(
//定义按钮的形状
shape = SegmentedButtonDefaults.itemShape(
index = index,
count = options.size
),
//点击按钮更新索引 selectedIndex
onClick = { selectedIndex = index },
//设置选中/未选中的背景以及内容颜色
// colors = SegmentedButtonDefaults.colors(
// //ContainerColor分段按钮的背景颜色
// activeContainerColor = Color.Red,//选中
// inactiveContainerColor = Color.LightGray,//未选中
// //ContentColor:选中状态下所有内容(包括文本和图标)的颜色
// activeContentColor=Color.White,//选中
// inactiveContentColor = Color.Black//未选中
// ),
// icon = {},//这样设置,选中的默认图标就会消失
icon ={
if (selectedIndex == index)
{
//从material系统库中设置自己想要的图标
Icon(
imageVector = Icons.Default.Star,
contentDescription = "选中",
tint = Color.Yellow
)
}
},
//根据 selectedIndex 设置按钮的选择状态
selected = index == selectedIndex,
//使用 Text 可组合函数显示按钮标签
label = { Text(label) }
)
}
}
}
效果如下(从库中选择自己想要的图标样式)
库中包含的图标有以下样式
2.1.1、设置美工提供的图标样式
单选分段按钮如果想要设置美工提供的图标样式,我们可以用Image,不用Icon
//设置美工设计师提供的图标用Image
Image(
painter = painterResource(id = R.drawable.icon_selected),
contentDescription = "已选中",
modifier = Modifier.size(24.dp)
)
2.2、多选分段按钮
此示例展示了如何创建带有图标的多选分段按钮,让用户可以选择多个选项,多选分段按钮样式设置与单选相似。
//可让用户选择 2 到 5 个项目
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun MultiChoiceSegmentedButton() {
//使用 remember 和 mutableStateOf初始化 selectedOptions 变量,以跟踪每个按钮的选中状态
//默认三个都不被选中
val selectedOptions = remember { mutableStateListOf(false, false, false) }
//定义表示按钮标签的 options 列表
val options = listOf("日", "周", "月")
//MultiChoiceSegmentedButtonRow 允许选择多个按钮
MultiChoiceSegmentedButtonRow {
//在 forEachIndexed 循环内,为每个选项创建一个 SegmentedButton
options.forEachIndexed { index, label ->
SegmentedButton(
//定义按钮的形状
shape = SegmentedButtonDefaults.itemShape(
index = index,
count = options.size
),
//设置选中/未选中的背景以及内容颜色
// colors = SegmentedButtonDefaults.colors(
// //ContainerColor分段按钮的背景颜色
// activeContainerColor = Color.Red,//选中
// inactiveContainerColor = Color.LightGray,//未选中
// //ContentColor:选中状态下所有内容(包括文本和图标)的颜色
// activeContentColor=Color.White,//选中
// inactiveContentColor = Color.Black//未选中
// ),
//checked 根据 selectedOptions 中的相应值设置按钮的选中状态
checked = selectedOptions[index],
//点击按钮时,onCheckedChange 会切换 selectedOptions 中相应项的选择状
onCheckedChange = {
selectedOptions[index] = !selectedOptions[index]
},
// icon = {},//这样设置,选中的默认图标就会消失
icon ={
if (selectedOptions[index]) {
//从material系统库中设置自己想要的图标
// Icon(
// imageVector = Icons.Default.Star,
// contentDescription = "选中",
// tint = Color.Yellow
// )
//设置美工设计师提供的图标用Image
Image(
painter = painterResource(id = R.drawable.icon_selected),
contentDescription = "已选中",
modifier = Modifier.size(24.dp)
)
}
},
//使用 Text 可组合函数显示按钮标签
label = { Text(label) }
)
}
}
}
多选按钮效果如下