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 选项文本长度,选项文本尽量简短,避免换行。

相关推荐
Android系统攻城狮2 小时前
Android ALSA驱动进阶之设置共享内存snd_pcm_lib_mmap_iomem:用法实例(九十九)
android·pcm·音频进阶·alsa驱动·android驱动
week_泽2 小时前
7、OpenCV ORB特征检测笔记
人工智能·笔记·opencv
sevenez2 小时前
职途引擎-产品需求文档
笔记
ZHANG13HAO2 小时前
Android 13 系统源码定制的保活方案,
android
94621931zyn65 小时前
关于应用 - Cordova 与 OpenHarmony 混合开发实战
笔记·python
Andy121386 小时前
网页笔记插件(chrome)开发记录
chrome·笔记·mfc
做cv的小昊10 小时前
计算机图形学:【Games101】学习笔记05——着色(插值、高级纹理映射)与几何(基本表示方法)
笔记·opencv·学习·计算机视觉·图形渲染·几何学
2501_9462309810 小时前
Cordova&OpenHarmony通知中心实现
android·javascript
csj5011 小时前
安卓基础之《(9)—中级控件(3)文本输入》
android