androidandroid-jetpack-composematerial3

Compose ExposedDropdownMenu cuts off top 4 items, cannot scroll to top


I am displaying ExposedDropdownMenus within an AlertDialog and when they are expanded, the top 4 items of the list are unavailable, and it is not possible to scroll to the top of the list.

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun MakeSelection(
    vinDescriptionFlow: MutableStateFlow<VinDescription>,
) {
    val vinDescriptionState = vinDescriptionFlow.collectAsState()
    val makeLabelString = "Make"
    val makes =
        SMSDatabase
            .database
            .vinMakeModel
            .observeDistinctMakes().collectAsState(
        initial = emptyList())
    var expanded by remember { mutableStateOf(false) }
    Row(
        modifier = Modifier
            .fillMaxWidth()
            .height(IntrinsicSize.Max)
    ) {
        ExposedDropdownMenuBox(
            modifier = Modifier
                .weight(1f),
            expanded = expanded,
            onExpandedChange = {
                expanded = !expanded
            }
        ) {
            OutlinedTextField(
                modifier = Modifier
                    .fillMaxWidth()
                    .menuAnchor(),
                readOnly = true,
                value = vinDescriptionState.value.make,
                onValueChange = {
                    vinDescriptionState.value.make = it
                },
                label = {
                    Text(makeLabelString)
                },
                placeholder = {
                    Text(makeLabelString.toUpperCase(Locale.current))
                },
                trailingIcon = {
                    ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded)
                }
            )
            ExposedDropdownMenu(
                expanded = expanded,
                onDismissRequest = {
                    expanded = false
                }
            ) {
                makes.value.forEach {
                    DropdownMenuItem(
                        text = { Text(it) },
                        onClick = {
                            vinDescriptionFlow.value.make = it
                            expanded = false
                        }
                    )
                }
            }
        }
        Button(
            modifier = Modifier
                .padding(Theme.TEXT_FIELD_BUTTON_PADDING)
                .width(IntrinsicSize.Min)
                .fillMaxHeight()
                .defaultMinSize(
                    minWidth = 85.dp,
                    minHeight = 0.dp
                ),
            shape = RoundedCornerShape(size = 6.dp),
            contentPadding = PaddingValues(
                start = 4.dp,
                top = 4.dp,
                end = 4.dp,
                bottom = 4.dp
            ),
            onClick = {

            }
        ) {
            Text(
                modifier = Modifier
                    .align(Alignment.CenterVertically),
                textAlign = TextAlign.Center,
                text = "QUICK JUMP")
        }
    }
}

Here is the dialog in which the dropdown is displayed:

@Composable
fun TowDialog(
    vinDescriptionFlow: MutableStateFlow<VinDescription>,
    show: MutableState<Boolean>,
    onConfirm: (VinDescription) -> Unit) {
    val vinDescriptionState = vinDescriptionFlow.collectAsState()
    AlertDialog(
        onDismissRequest = {
            show.value = false
        },
        confirmButton = {
            TextButton(
                onClick = {
                    onConfirm(vinDescriptionState.value)
                }
            ) {
                Text("Save")
            }
        },
        dismissButton = {
            TextButton(
                onClick = {
                    show.value = false
                }
            ) {
                Text("Cancel")
            }
        },
        text = {
            Column {
                MakeSelection(vinDescriptionFlow = vinDescriptionFlow)
                ModelSelection(vinDescriptionFlow = vinDescriptionFlow)
                ColorSelection(vinDescriptionFlow = vinDescriptionFlow)
            }
        })
}

Here is the resulting screen. In this image, the top few results are missing. Above "AMC" should be "AA", "ACURA", "ALFA ROMEO", "AM GENERAL" and it is not possible to scroll up higher, but it is possible to scroll down all the way to the bottom.


Solution

  • Updated comment:

    So after checking on an Android 9 device, the issue was replicated. After debugging and trying multiple iterations of fixes, I finally found a solution that can resolve the issue.

    1. First, remove the height from the row of MakeSelection Composable.

    .height(IntrinsicSize.Max)

    It would look like this:

    Row(
        modifier = Modifier
            .fillMaxWidth()
    ) {
        ExposedDropdownMenuBox(
            modifier = Modifier
                .weight(1f),
            expanded = expanded,
            onExpandedChange = {
                expanded = !expanded
                println("expanded clicked")
            }
        )
    
    1. Next, apply the maximum height to the ExposedDropdownMenu as previously suggested.

      ExposedDropdownMenu(
          modifier = Modifier.fillMaxHeight(),
          expanded = expanded,
          onDismissRequest = {
               expanded = false
          }
      )
      
    2. After following these steps, set the max size for the dialog and adjust the padding according to your preferences. I dynamically adjusted it based on the device height as suggested earlier.

      val configuration = LocalConfiguration.current
      val screenHeight = configuration.screenHeightDp.dp
      val dialogPadding = (screenHeight.value *  0.3).roundToInt()
      AlertDialog(
          modifier = Modifier
              .fillMaxSize()
              .padding(vertical = (dialogPadding.dp)),
          onDismissRequest = {
              show.value = false
          },
        )
      

    Here are the Attached are screenshots from a device running Android 9, one before applying the fix and the other after applying the fix. Without fix

    After fix

    Previous comment:

    I tried your code, and the mentioned issue didn't replicate with it. Things you can try:

    The problem is something else and not with your current code. I've passed a list of strings (car makes) with a size of 50 to populate the data in the exposed dropdown composable. I was able to scroll to the top and the bottom of the expanded list. Here is the attached screenshot:

    Dialog screenshot