Jetpack Compose实现类似传统的 Spinner 组件

由于之前的开发习惯,使用 Compose 开发 UI 时想使用 Spinner 组件,就选择使用 AndroidView 加载 Spinner,但是测试发现有些手机上有时候下拉列表不能滚动,数据更新与选中事件的关联也会导致数据出错,可能再花点时间也能修复,但是既然选择了 Compose,那就以 Compose 的方式来实现吧,见其名知其意,Compose 意思就是组合,Android新的声明式UI,一个用 @Compose 注解标记的函数就代表一个组件,而且可以嵌套组合,越是底层的组合元素越灵活,但是相对应地,需要掌握的东西也比较多,使用难度较高,官方提供了丰富的 Material 组件,对于一般开发者还是比较容易上手的,下面就来使用 DropdownMenu 和 TextButton 组合实现跟 Spinner 一样的组件:

@Composable
fun  JSpinner(
    items: List,
    selectedIndex: Int,
    onMenuItemClick: (index: Int, item: T) -> Unit,
    modifier: Modifier = Modifier,
) {
    //使用 AndroidView 加载 android.widget.Spinner 有时候下拉列表无法滚动,数据也容易因为选中事件出错
    var expanded by remember { mutableStateOf(false) }
    var selectedItem by remember { mutableStateOf("") }
    // remember 记忆的委托变量并不是传统意义上的函数内部的局部变量
    // 传给 mutableStateOf() 函数的值只在首次创建变量时有效
    // 所以这里显式地给 selectedItem 赋值,以更新其值
    selectedItem = if (items.isEmpty()) "" else items[selectedIndex].toString()

    //下面使用 DropdownMenu 和 TextButton 组合实现跟 Spinner 一样的组件
    DropdownMenu(expanded = expanded, onDismissRequest = { expanded = false }) {
        items.forEachIndexed { index, item ->
            DropdownMenuItem(onClick = {
                expanded = false//关闭下拉菜单窗口
                selectedItem = item.toString()
                onMenuItemClick(index, item)
            }) {
                Text(
                    text = item.toString(),
                    color = if (index == selectedIndex) Color(0xFF6200EE) else Color.Black,
                    fontWeight = if (index == selectedIndex) FontWeight.Bold else FontWeight.Normal,
                )
            }
        }
    }
    TextButton(
        modifier = modifier,
        onClick = { if (items.isNotEmpty()) expanded = !expanded }
    ) {
        Text(text = selectedItem, modifier = Modifier.weight(1f))
        Icon(Icons.Default.ArrowDropDown, contentDescription = "")
    }
}


@Preview(showBackground = false)
@Composable
fun JSpinnerPreview() {
    JSpinner(
        items = (0..10).map { "item ${it + 1}" }.toList(),
        selectedIndex = 0,
        onMenuItemClick = { index, item ->
            println("index=$index, item=$item")
        },
    )
}

下面是预览效果:

Jetpack Compose实现类似传统的 Spinner 组件_第1张图片

Jetpack Compose实现类似传统的 Spinner 组件_第2张图片

你可能感兴趣的:(android,ui)