[英]Jetpack Compose: Mimicking spinner.setSelection() inside of a DropDownMenu
用例是您在下拉菜单中有 10 或 100 项,下拉选项有一些排序 - 如数字值或单词的字母列表 - 并且选择是连续进行的。
当用户重新打开菜单时,您希望它在与他们上次选择的区域相同的区域中打开,例如,您不会从“car”跳转到“apple”,而是从“car”跳转到“cat” ”。 或者,如果他们只是选择查看订单号 358,他们可以快速查看订单号 359。
使用视图,您可以创建一个Spinner
并将所有项目放入ArrayAdapter
中,然后调用spinner.setSelection()
直接滚动到您想要的索引。
DropdownMenu
没有类似HorizontalPager
ntalPager 的scrollToPage()
的东西。 那么可能存在哪些解决方案来实现这一目标呢?
到目前为止,我已经尝试将verticalScroll()
添加到DropdownMenu
的修饰符并尝试对 scrollState 进行算术运算。 但它在运行时崩溃,并显示该组件具有无限高度的错误,如果您尝试将LazyColumn
等可滚动组件嵌套在具有verticalScroll 的Column
内,则会出现相同的错误。
我将在这里发布更详细的答案,因为我不想用上面的评论误导任何人。
如果您在 Android Studio 中,请单击鼠标悬停快速文档框上的三个点和 select “编辑源代码”以在 AndroidMenu.ZC31B32364CE19CA8FCD150A4CEECk 中打开DropdownMenu
的源代码。 然后观察它使用了一个名为DropdownMenuItemContent
的组合。 再次编辑源代码,您将在 Menu.kt 中。
你会看到这个:
@Composable
internal fun DropdownMenuContent(
...
...
...
{
Column(
modifier = modifier
.padding(vertical = DropdownMenuVerticalPadding)
.width(IntrinsicSize.Max)
.verticalScroll(rememberScrollState()),//<-We want this
content = content
)
}
因此,在您的自定义组合中,只需将rememberScrollState()
替换为您最喜欢的 ScrollState 变量名称。
然后将该引用一直链接到您的原始视图。
访问 ScrollState
@Composable
fun MyCustomDropdownMenu(
expanded:Boolean,
scrollStateProvidedByTopParent:ScrollState,
...
...
)
{...}
@Composable
fun MyCustomDropdownMenuContent(
scrollStateProvidedByTopParent:ScrollState,
...
...
)
{...}
//And now for your actual content
@Composable
fun TopParent(){
val scrollStateProvidedByTopParent=rememberScrollState()
val spinnerExpanded by remember{mutableStateOf(false)}
...
...
Box{
Row(modifier=Modifier.clickable(onClick={spinnerExpanded=!spinnerExpanded}))//<-More about this line in the sequel
{
Text("Options")
Icon(imageVector = Icons.Filled.ArrowDropDown, contentDescription = "")
MyCustomDropdownMenu(
expanded = spinnerExpanded,
scrollStateProvidedByTopParent=scrollStateProvidedByTopParent,
onDismissRequest = { spinnerExpanded = false })
{//your spinner content}
}
}
}
上面只指定了如何访问DropdownMenu
的ScrollState
。 但是一旦你有了ScrollState
,你就必须做一些算术才能让滚动 position 在它打开时正确。 这是一种看起来不错的方法。
计算滚动距离
即使在明确设置菜单项的内容之后,如果我依赖这些值,距离也永远不会完全正确。 因此,我在菜单项的Text
中使用了onTextLayout
回调,以便在渲染时获得真实的Text
高度。 然后我将该值用于算术。 它看起来像这样:
@Composable
fun TopParent(){
val scrollStateProvidedByTopParent=rememberScrollState()
val spinnerExpanded by remember{mutableStateOf(false)}
val chosenText:String by remember{mutableStateOf(myListOfSpinnerOptions[0])
val height by remember{mutableStateOf(0)}
val heightHasBeenChecked by remember{mutableStateOf(false)}
val coroutineScope=rememberCoroutineScope()
...
...
Box{
Row(modifier=Modifier.clickable(onClick={spinnerExpanded=!spinnerExpanded
coroutineScope.launch{scrollStateProvidedByTopParent.scrollTo(height*myListOfSpinnerOptions.indexOf[chosenText])}}))//<-This gets some arithmetic for scrolling distance
{
Text("Options")
Icon(imageVector = Icons.Filled.ArrowDropDown, contentDescription = "")
MyCustomDropdownMenu(
expanded = spinnerExpanded,
scrollStateProvidedByTopParent=scrollStateProvidedByTopParent,
onDismissRequest = { spinnerExpanded = false }) {
myListOfSpinnerOptions.forEach{option->
DropdownMenuItem(onClick={
chosenText=option
spinnerExpanded=false
}){
Text(option,onTextLayout={layoutResult->
if (!heightHasBeenChecked){
height=layoutResults.size.height
heightHasBeenChecked=true
}
}
)
}
}
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.