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 小时前
c++ 学习笔记之 shared_ptr
c++·笔记·学习
claider15 小时前
Vim User Manual 阅读笔记 usr_08.txt Splitting windows 窗口分割
笔记·编辑器·vim
am心15 小时前
学习笔记-用户下单
笔记·学习
SHEN_ZIYUAN16 小时前
深度解析:从 AnimationHandler 原理看 Android 动画内存泄漏
android
冬奇Lab16 小时前
稳定性性能系列之十六——车机特定场景:黑卡死问题分析与排查实战
android·性能优化
座山雕~17 小时前
Springboot
android·spring boot·后端
香气袭人知骤暖18 小时前
SQL慢查询常见优化步骤
android·数据库·sql
丨康有为丨18 小时前
Android滑动冲突详解(场景+解决)
android
要做朋鱼燕19 小时前
【AES加密专题】3.工具函数的编写(1)
笔记·密码学·嵌入式·aes
千里马学框架19 小时前
疑难ANR面试题:crash导致ANR深入剖析
android·智能手机·framework·perfetto·性能·anr·小米汽车