Sid*_*ora 13 android kotlin android-jetpack-compose android-jetpack-compose-list
所以我现在有点进退两难。
开始时
我有一个国家/地区列表,我想允许用户通过显示下拉菜单来选择其中任何一个,之前没有jetpack compose方式,我有一个扩展,这View反过来View.setupDropDown加载aListPopupWindow并将其锚定到当前视图,并显示所有项目并且工作完美,没有卡顿或任何帧丢失。
喜欢
val dropDown = ListPopupWindow(context)
dropDown.setAdapter(
ArrayAdapter(
context,
android.R.layout.simple_spinner_dropdown_item,
list.map { itemFormatter(it) })
)
Run Code Online (Sandbox Code Playgroud)
并显示它,或者我可以使用自定义
泡菜
因此,现在我正在 Jetpack Compose 中构建相同的体验,并使用DropDownMenu它加载所有这些项目,Column当项目数量较少时,它可以正常工作,但是,当涉及大量项目时,例如包含更多项目的列表然后是 100 个项目,它会丢掉几帧,并PopUp在延迟后显示。
我查看了内部并尝试通过将所有这些文件复制到示例项目中来替换Column,LazyColumn但这不起作用
Intrinsic measurements is not yet supported for the Subcomposables,它会抛出异常并失败。
DropdownMenu(
toggle = toggle,
expanded = showMenu,
onDismissRequest = { onDismiss() },
) {
options.forEach{ item ->
DropdownMenuItem(onClick = {
onDismiss()
}) {
Text(text = item)
}
}
}
Run Code Online (Sandbox Code Playgroud)
LazyColumn如果我使用修饰符将固定的高度和宽度应用于 ,它工作得非常好Modifier.height(200.dp).widht(300.dp)
我在问题跟踪器中查找,发现这个问题相关但不相同,建议是执行我上面所做的操作。
不知道在这里使用什么,因为 Compose 仍然是新的,不知道哪个组件适合。
更新:有一个关于此问题的问题跟踪报告。
您可以尝试其中也有效的解决方案(如果您还没有惰性列)
DropdownMenu(
expanded = expanded,
onDismissRequest = { expanded = false },
) {
Box(modifier = Modifier.size(width = 100.dp, height = 300.dp)) {
LazyColumn {
items(largeList) { item ->
DropdownMenuItem(
text = { Text(text = item) },
onClick = {
expanded = false
},
)
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
可能有点晚了,但我找到了这篇文章
这对我有用。
在此处添加代码以供将来使用:
@Composable
fun <T> LargeDropdownMenu(
modifier: Modifier = Modifier,
enabled: Boolean = true,
label: String,
notSetLabel: String? = null,
items: List<T>,
selectedIndex: Int = -1,
onItemSelected: (index: Int, item: T) -> Unit,
selectedItemToString: (T) -> String = { it.toString() },
drawItem: @Composable (T, Boolean, Boolean, () -> Unit) -> Unit = { item, selected, itemEnabled, onClick ->
LargeDropdownMenuItem(
text = item.toString(),
selected = selected,
enabled = itemEnabled,
onClick = onClick,
)
},
) {
var expanded by remember { mutableStateOf(false) }
Box(modifier = modifier.height(IntrinsicSize.Min)) {
OutlinedTextField(
label = { Text(label) },
value = items.getOrNull(selectedIndex)?.let { selectedItemToString(it) } ?: "",
enabled = enabled,
modifier = Modifier.fillMaxWidth(),
trailingIcon = {
val icon = expanded.select(Icons.Filled.ArrowDropUp, Icons.Filled.ArrowDropDown)
Icon(icon, "")
},
onValueChange = { },
readOnly = true,
)
// Transparent clickable surface on top of OutlinedTextField
Surface(
modifier = Modifier
.fillMaxSize()
.padding(top = 8.dp)
.clip(MaterialTheme.shapes.extraSmall)
.clickable(enabled = enabled) { expanded = true },
color = Color.Transparent,
) {}
}
if (expanded) {
Dialog(
onDismissRequest = { expanded = false },
) {
MyTheme {
Surface(
shape = RoundedCornerShape(12.dp),
) {
val listState = rememberLazyListState()
if (selectedIndex > -1) {
LaunchedEffect("ScrollToSelected") {
listState.scrollToItem(index = selectedIndex)
}
}
LazyColumn(modifier = Modifier.fillMaxWidth(), state = listState) {
if (notSetLabel != null) {
item {
LargeDropdownMenuItem(
text = notSetLabel,
selected = false,
enabled = false,
onClick = { },
)
}
}
itemsIndexed(items) { index, item ->
val selectedItem = index == selectedIndex
drawItem(
item,
selectedItem,
true
) {
onItemSelected(index, item)
expanded = false
}
if (index < items.lastIndex) {
Divider(modifier = Modifier.padding(horizontal = 16.dp))
}
}
}
}
}
}
}
}
@Composable
fun LargeDropdownMenuItem(
text: String,
selected: Boolean,
enabled: Boolean,
onClick: () -> Unit,
) {
val contentColor = when {
!enabled -> MaterialTheme.colorScheme.onSurface.copy(alpha = ALPHA_DISABLED)
selected -> MaterialTheme.colorScheme.primary.copy(alpha = ALPHA_FULL)
else -> MaterialTheme.colorScheme.onSurface.copy(alpha = ALPHA_FULL)
}
CompositionLocalProvider(LocalContentColor provides contentColor) {
Box(modifier = Modifier
.clickable(enabled) { onClick() }
.fillMaxWidth()
.padding(16.dp)) {
Text(
text = text,
style = MaterialTheme.typography.titleSmall,
)
}
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
var selectedIndex by remember { mutableStateOf(-1) }
LargeDropdownMenu(
label = "Sample",
items = listOf("Item 1", "Item 2", "Item 3"),
selectedIndex = selectedIndex,
onItemSelected = { index, _ -> selectedIndex = index },
)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1494 次 |
| 最近记录: |