Cannot make ExposedDropdownMenu same width as OutlinedTextField

I faced the following problem - items of the dropdown are not the same width as OutlinedTextField

Looked for the solution - found the following:

  1. Add the variable to keep textField width:

    var textFieldSize by remember { mutableStateOf(Size.Zero) }
    
  2. Set the value in the onGloballyPositioned of TextField

    onGloballyPositioned { coordinates ->
        textFieldSize = coordinates.size.toSize()
    }
    
  3. Read the value in ExposedDropdownMenu

    ExposedDropdownMenu(
        expanded = expanded,
        onDismissRequest = { expanded = false },
        modifier = Modifier
            .background(Color.White)
            .width(with(LocalDensity.current) { textFieldSize.width.toDp() })
    )
    

The problem is that it works fine with DropdownMenu, but doesn't work with ExposedDropdownMenu. What's the problem?

Here's the full code:

var expanded by remember { mutableStateOf(false) }
val sexList by remember { mutableStateOf(listOf("Male", "Female")) }
var textFieldSize by remember { mutableStateOf(Size.Zero) }

val icon = if (expanded)
    Icons.Filled.ArrowDropUp
else
    Icons.Filled.ArrowDropDown

ExposedDropdownMenuBox(
    modifier = modifier
        .clickable(onClick = { expanded = true }),
    expanded = expanded,
    onExpandedChange = { expanded = !expanded }
) {
    OutlinedTextField(
        value = "",
        onValueChange = {},
        modifier = Modifier
            .fillMaxWidth()
            .onGloballyPositioned { coordinates ->
                textFieldSize = coordinates.size.toSize()
            },
        colors = TextFieldDefaults.textFieldColors(
            backgroundColor = BorderColor,
            unfocusedIndicatorColor = Color.Transparent,
            focusedIndicatorColor = BrandColor,
            focusedLabelColor = BrandColor,
        ),
        leadingIcon = {
            Image(
                painter = painterResource(id = R.drawable.ic_complete_registration_sex),
                contentDescription = null
            )
        },
        trailingIcon = { Icon(icon, null) },
        shape = RoundedCornerShape(Dimen.Dimen14),
        label = {
            Text(
                "Choose Gender",
                style = PoppinsNormalStyle14
            )
        },
        readOnly = true
    )

    ExposedDropdownMenu(
        expanded = expanded,
        onDismissRequest = { expanded = false },
        modifier = Modifier
            .background(Color.White)
            .width(with(LocalDensity.current) { textFieldSize.width.toDp() })
    ) {
        sexList.forEach {
            DropdownMenuItem(
                onClick = { expanded = false },
            ) {
                Text(it, style = PoppinsNormalStyle12Gray2)
            }
        }
    }
}

ExposedDropdownMenuBox is built to calculate width for you so you don't have to use all this onGloballyPositioned related logic.

The fact that it doesn't work is a known issue.

Until it's fixed it's recommended to use DropdownMenu with Modifier.exposedDropdownSize()(this modifier will apply the width calculated by ExposedDropdownMenuBox) instead of ExposedDropdownMenu:

DropdownMenu(
    expanded = expanded,
    onDismissRequest = { expanded = false },
    modifier = Modifier
        .background(Color.White)
        .exposedDropdownSize()
) {
    sexList.forEach {
        DropdownMenuItem(
            onClick = { expanded = false },
        ) {
            Text(it, style = PoppinsNormalStyle12Gray2)
        }
    }
}