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.
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.
.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")
}
)
Next, apply the maximum height to the ExposedDropdownMenu as previously suggested.
ExposedDropdownMenu(
modifier = Modifier.fillMaxHeight(),
expanded = expanded,
onDismissRequest = {
expanded = false
}
)
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.
Previous comment:
I tried your code, and the mentioned issue didn't replicate with it. Things you can try:
Give max height to the exposed drop down menu like below code:
ExposedDropdownMenu(
modifier = Modifier.fillMaxHeight(),
expanded = expanded,
onDismissRequest = {
expanded = false
}
)
Check for any other obstruction on the UI by other composables.
Since its a dialog, you can try giving fillMaxSize() to the modifier so that the dialog can use whole screen space then give vertical padding accordingly. See example:
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
},
)
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: