Compose笔记(六十三)--SegmentedButton

这一节主要了解一下Compose中的SegmentedButton,在Jetpack Compose中,SegmentedButton是一种用于在多个互斥选项间快速切换的UI组件,通常呈现为一组水平排列的按钮,用户只能选中其中一个,或者非互斥选项间,用户可选其中多个,简单总结如下:

场景:

1 选项筛选,在列表或表格中切换筛选条件

2 视图切换,在同一个页面中切换不同的视图模式

3 表单中的单选输入,在表单中选择性别、支付方式等单选字段

栗子:

Kotlin 复制代码
import androidx.compose.material3.SegmentedButton
import androidx.compose.material3.SegmentedButtonDefaults
import androidx.compose.material3.SingleChoiceSegmentedButtonRow
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue


@Composable
fun SegmentedButtonDemo() {
    var selectedIndex by remember { mutableIntStateOf(0) }
    val options = listOf("日", "周", "月")

    SingleChoiceSegmentedButtonRow {
        options.forEachIndexed { index, label ->
            SegmentedButton(
                shape = SegmentedButtonDefaults.itemShape(index, options.size),
                onClick = { selectedIndex = index },
                selected = index == selectedIndex,
                label = { Text(label) }
            )
        }
    }
}
Kotlin 复制代码
import androidx.compose.foundation.layout.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

@Composable
fun SegmentedButtonDemo() {
    val hobbyTags = listOf("篮球", "音乐", "阅读", "游戏", "摄影")
    val checkedStates = remember {
        mutableStateOf(
            hobbyTags.associateWith { false }.toMutableMap()
        )
    }
    val selectedHobbies = remember { mutableStateOf(setOf<String>()) }

    MultiChoiceSegmentedButtonRow(
        modifier = Modifier.padding(16.dp),
        space = SegmentedButtonDefaults.BorderWidth 
    ) {
        hobbyTags.forEachIndexed { index, tag ->
            val shape = SegmentedButtonDefaults.itemShape(
                index = index,
                count = hobbyTags.size,
                baseShape = MaterialTheme.shapes.small 
            )

            SegmentedButton(
                 checked = selectedHobbies.value.contains(tag),
                onCheckedChange = { isChecked ->
                    selectedHobbies.value = if (isChecked) {
                        selectedHobbies.value + tag
                    } else {
                        selectedHobbies.value - tag
                    }
                },
                shape = shape,
                modifier = Modifier,
                enabled = true,
                colors = SegmentedButtonDefaults.colors(),
                border = SegmentedButtonDefaults.borderStroke(
                    color = MaterialTheme.colorScheme.outline
                ),
                label = { Text(tag) }
            )
        }
    }
   
    Text(
        modifier = Modifier.padding(start = 16.dp, top = 8.dp),
        text = "当前选中爱好:${
             if (selectedHobbies.value.isEmpty()) "无" else selectedHobbies.value.joinToString(", ")
        }",
        style = MaterialTheme.typography.bodyMedium
    )
}
Kotlin 复制代码
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.MultiChoiceSegmentedButtonRow
import androidx.compose.material3.SegmentedButton
import androidx.compose.material3.SegmentedButtonDefaults
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.viewmodel.compose.viewModel

@Composable
fun SegmentedButtonDemo(
    viewModel: LanguageSelectViewModel = viewModel()
) {
    val languageOptions = listOf(
        LanguageOption("zh-CN", "中文"),
        LanguageOption("en-US", "英文"),
        LanguageOption("ja-JP", "日语"),
        LanguageOption("ko-KR", "韩语")
    )
    val selectedLanguages = viewModel.selectedLanguages.collectAsStateWithLifecycle(initialValue = emptySet())

    MultiChoiceSegmentedButtonRow(
        modifier = Modifier.padding(horizontal = 0.dp),
        space = SegmentedButtonDefaults.BorderWidth
    ) {
        languageOptions.forEachIndexed { index, option ->
            val shape = SegmentedButtonDefaults.itemShape(
                index = index,
                count = languageOptions.size,
                baseShape  = MaterialTheme.shapes.small
            )

            SegmentedButton(
                checked = selectedLanguages.value.contains(option.code),
                onCheckedChange = { isChecked ->
                    viewModel.updateLanguageSelection(option.code, isChecked)
                },
                shape = shape,
                colors = SegmentedButtonDefaults.colors(
                ),
                label = { Text(option.name) }
            )
        }
    }
}
Kotlin 复制代码
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch

data class LanguageOption(
    val code: String,
    val name: String 
)

class LanguageSelectViewModel : ViewModel() {
    private val _selectedLanguages = MutableStateFlow(setOf<String>())
    val selectedLanguages: StateFlow<Set<String>> = _selectedLanguages.asStateFlow()

    fun updateLanguageSelection(code: String, isChecked: Boolean) {
        viewModelScope.launch {
            _selectedLanguages.value = if (isChecked) {
                _selectedLanguages.value + code
            } else {
                _selectedLanguages.value - code
            }
        }
    }
}

注意:

1 选项数量限制,选项数量尽量控制在2-5个,过多会导致按钮过小,难以点击。

2 选项文本长度,选项文本尽量简短,避免换行。

相关推荐
工程师老罗15 小时前
如何在Android工程中配置NDK版本
android
wdfk_prog16 小时前
[Linux]学习笔记系列 -- [drivers][input]input
linux·笔记·学习
ouliten17 小时前
cuda编程笔记(36)-- 应用Tensor Core加速矩阵乘法
笔记·cuda
孞㐑¥17 小时前
算法——BFS
开发语言·c++·经验分享·笔记·算法
Libraeking18 小时前
破壁行动:在旧项目中丝滑嵌入 Compose(混合开发实战)
android·经验分享·android jetpack
mango_mangojuice19 小时前
Linux学习笔记(make/Makefile)1.23
java·linux·前端·笔记·学习
工程师老罗19 小时前
YOLOv1 核心知识点笔记
笔记·yolo
市场部需要一个软件开发岗位19 小时前
JAVA开发常见安全问题:Cookie 中明文存储用户名、密码
android·java·安全
半壶清水20 小时前
[软考网规考点笔记]-软件开发、项目管理与知识产权核心知识与真题解析
网络·笔记·压力测试
JMchen12321 小时前
Android后台服务与网络保活:WorkManager的实战应用
android·java·网络·kotlin·php·android-studio