[英]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.