You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Kotlin:如何让Compose函数接收任意枚举类参数

让Compose对话框支持任意指定格式的枚举类参数

1. 定义通用接口统一枚举属性

先创建一个接口,规范所有目标枚举类的属性结构:

interface EnumItem {
    val id: Int
    val titleId: Int
}

2. 让所有枚举类实现该接口

修改你的枚举类,实现上面的EnumItem接口:

enum class MyEnum1(override val id: Int, override val titleId: Int) : EnumItem {
    A1(0, R.string.a1),
    B1(1, R.string.b1),
    // ... 其他枚举值
}

enum class MyEnum2(override val id: Int, override val titleId: Int) : EnumItem {
    A2(0, R.string.a2),
    B2(1, R.string.b2),
    // ... 其他枚举值
}

3. 实现支持泛型枚举的Compose对话框

提供两种实现方案,按需选择:

方案一:通过KClass传递枚举类(适配动态场景)

适合需要根据业务逻辑动态切换枚举类型的场景:

@Composable
fun <T> ListDialog(
    onDismissRequest: () -> Unit,
    onItemSelected: (T) -> Unit,
    enumClass: KClass<T>
) where T : Enum<T>, T : EnumItem {
    // 获取枚举的所有常量值
    val enumValues = enumClass.java.enumConstants ?: emptyArray()

    AlertDialog(
        onDismissRequest = onDismissRequest,
        title = { Text("选择选项") },
        text = {
            LazyColumn {
                items(enumValues) { item ->
                    Text(
                        text = stringResource(item.titleId),
                        modifier = Modifier
                            .fillMaxWidth()
                            .clickable {
                                onItemSelected(item)
                                onDismissRequest()
                            }
                            .padding(16.dp)
                    )
                }
            }
        },
        confirmButton = {
            TextButton(onClick = onDismissRequest) {
                Text("取消")
            }
        }
    )
}

调用示例:

// 使用MyEnum1
ListDialog(
    onDismissRequest = { /* 处理对话框关闭逻辑 */ },
    onItemSelected = { selectedItem ->
        // 处理选中逻辑,如获取selectedItem.id或titleId
    },
    enumClass = MyEnum1::class
)

// 使用MyEnum2
ListDialog(
    onDismissRequest = { /* 处理对话框关闭逻辑 */ },
    onItemSelected = { selectedItem ->
        // 处理选中逻辑
    },
    enumClass = MyEnum2::class
)

方案二:使用reified泛型(调用更简洁)

通过inline函数结合reified泛型,省去传递::class的步骤,代码更简洁:

@Composable
inline fun <reified T> ListDialog(
    onDismissRequest: () -> Unit,
    onItemSelected: (T) -> Unit
) where T : Enum<T>, T : EnumItem {
    // 直接获取枚举所有常量值
    val enumValues = enumValues<T>()

    AlertDialog(
        onDismissRequest = onDismissRequest,
        title = { Text("选择选项") },
        text = {
            LazyColumn {
                items(enumValues) { item ->
                    Text(
                        text = stringResource(item.titleId),
                        modifier = Modifier
                            .fillMaxWidth()
                            .clickable {
                                onItemSelected(item)
                                onDismissRequest()
                            }
                            .padding(16.dp)
                    )
                }
            }
        },
        confirmButton = {
            TextButton(onClick = onDismissRequest) {
                Text("取消")
            }
        }
    )
}

调用示例:

// 使用MyEnum1
ListDialog<MyEnum1>(
    onDismissRequest = { /* 处理对话框关闭逻辑 */ },
    onItemSelected = { selectedItem ->
        // 处理选中逻辑
    }
)

// 使用MyEnum2
ListDialog<MyEnum2>(
    onDismissRequest = { /* 处理对话框关闭逻辑 */ },
    onItemSelected = { selectedItem ->
        // 处理选中逻辑
    }
)

核心说明

  • 泛型约束where T : Enum<T>, T : EnumItem确保传入的类型必须是枚举类,且具备id和titleId属性,保证代码安全。
  • 两种方案都无需提前将枚举转换为List<Pair<Int,Int>>,直接操作枚举对象更直观,也避免了类型转换的潜在问题。

内容的提问来源于stack exchange,提问作者LGstudio

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 16:33:28