簡體   English   中英

Jetpack Compose:在 DropDownMenu 中模仿 spinner.setSelection()

[英]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內,則會出現相同的錯誤。

這是一個已知問題

DropdownMenu內部有自己的垂直滾動修改器,並且沒有 API 可以使用它。

在通過提供合適的 API 解決此問題之前,我能想到的唯一解決方法是創建自己的視圖 - 您可以參考DropdownMenu的源代碼。

我將在這里發布更詳細的答案,因為我不想用上面的評論誤導任何人。

如果您在 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}

       }
    }
}

上面只指定了如何訪問DropdownMenuScrollState 但是一旦你有了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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM