go to index

Jetpack Compose segmented control组件

read time 2 min read
Jetpack Compose Segmented 组件 Android 安卓

概述

Jetpack Compose 默认并没有提供 Segmented Control 组件,因此我们可以自定义一个。本文将介绍如何创建一个功能齐全的 SegmentedControl 组件,并提供使用示例。

自定义 SegmentedControl 组件

示例代码

kotlin
@Composable
fun SegmentedControl(
    items: List<String>,
    defaultSelectedItemIndex: Int = 0,
    useFixedWidth: Boolean = false,
    itemWidth: Dp = 120.dp,
    cornerRadius: Int = 10,
    @ColorRes color: Int = R.color.teal_200,
    onItemSelection: (selectedItemIndex: Int) -> Unit
) {
    val selectedIndex = remember { mutableStateOf(defaultSelectedItemIndex) }
    
    Row(
        modifier = Modifier
            .fillMaxWidth()
            .padding(horizontal = 8.dp)
    ) {
        items.forEachIndexed { index, item ->
            OutlinedButton(
                modifier = when {
                    useFixedWidth -> Modifier
                        .width(itemWidth)
                        .zIndex(if (selectedIndex.value == index) 1f else 0f)
                    else -> Modifier
                        .wrapContentSize()
                        .zIndex(if (selectedIndex.value == index) 1f else 0f)
                },
                onClick = {
                    selectedIndex.value = index
                    onItemSelection(selectedIndex.value)
                },
                shape = when (index) {
                    0 -> RoundedCornerShape(
                        topStart = cornerRadius.dp,
                        bottomStart = cornerRadius.dp
                    )
                    items.size - 1 -> RoundedCornerShape(
                        topEnd = cornerRadius.dp,
                        bottomEnd = cornerRadius.dp
                    )
                    else -> RoundedCornerShape(0.dp)
                },
                border = BorderStroke(
                    1.dp, 
                    if (selectedIndex.value == index) {
                        colorResource(id = color)
                    } else {
                        colorResource(id = color).copy(alpha = 0.75f)
                    }
                ),
                colors = if (selectedIndex.value == index) {
                    ButtonDefaults.outlinedButtonColors(
                        backgroundColor = colorResource(id = color),
                        contentColor = Color.White
                    )
                } else {
                    ButtonDefaults.outlinedButtonColors(
                        backgroundColor = Color.Transparent,
                        contentColor = colorResource(id = color).copy(alpha = 0.9f)
                    )
                },
            ) {
                Text(
                    text = item,
                    fontWeight = FontWeight.Normal,
                    color = if (selectedIndex.value == index) {
                        Color.White
                    } else {
                        colorResource(id = color).copy(alpha = 0.9f)
                    }
                )
            }
        }
    }
}

使用示例

kotlin
val genders = listOf("Male", "Female")

SegmentedControl(
    items = genders,
    defaultSelectedItemIndex = 0
) { selectedIndex ->
    Log.e("CustomToggle", "Selected item: ${genders[selectedIndex]}")
}

参数说明

  • items: 要显示在 SegmentedControl 中的项目列表。
  • defaultSelectedItemIndex: 默认选中的项目索引,默认为 0
  • useFixedWidth: 是否使用固定宽度,默认为 false
  • itemWidth: 每个项目的宽度,默认为 120.dp
  • cornerRadius: 圆角半径,默认为 10
  • color: 颜色资源 ID,默认为 R.color.teal_200
  • onItemSelection: 当选择项发生变化时的回调函数。