0

I have the following where I want to display the dropdownmenu on the left and I want to display on the right.

enter image description here

I have the following code, that uses a Scaffold and in that I have a topBar with a column which I have my AgendaTopBar and the AgendaDropDownMenu below that which is align(Alignment.End)

 Scaffold(
        modifier = modifier,
        topBar = {
            Column(modifier = Modifier.fillMaxWidth()) {
                AgendaTopBar(
                    modifier = Modifier
                        .fillMaxWidth()
                        .background(color = MaterialTheme.colorScheme.backgroundBackColor)
                        .padding(start = 16.dp, end = 16.dp, top = 8.dp, bottom = 8.dp),
                    initials = agendaScreenState.usersInitials,
                    displayMonth = agendaScreenState.selectedDate.month.toString(),
                    onProfileButtonClicked = {
                        agendaScreenEvent(AgendaScreenEvent.OnOpenLogoutDropDownMenu(shouldOpen = true))
                    },
                    onDateClicked = {
                        calendarState.show()
                    },
                )

                AgendaDropDownMenu(
                    modifier = Modifier
                        .background(color = MaterialTheme.colorScheme.dropDownMenuBackgroundColor)
                        .align(Alignment.End),
                    shouldOpenDropdown = agendaScreenState.shouldOpenLogoutDropDownMenu,
                    onCloseDropdown = {
                        agendaScreenEvent(
                            AgendaScreenEvent.OnChangedShowDropdownStatus(shouldOpen = false)
                        )
                    },
                    listOfMenuItemId = listOf(me.androidbox.presentation.R.string.logout),
                    onSelectedOption = { _ ->
                        agendaScreenEvent(AgendaScreenEvent.OnOpenLogoutDropDownMenu(shouldOpen = false))
                        onLogout()
                    }
                )
            }
        },
        floatingActionButton = { 
ant2009
  • 27,094
  • 154
  • 411
  • 609
  • Can you add `AgendaDropDownMenu` source code? – beigirad Apr 29 '23 at 07:25
  • Check out [this answer](https://stackoverflow.com/a/68728525/3585796) for some details of how dropdown menu should be used. Thracian's answer seems legit, could you clarify what's wrong with it for you? – Phil Dukhov May 02 '23 at 09:30

1 Answers1

1

The reason Modifier.align doesn't work is how DropdownMenu is created. For align to work it should be applied to direct child of Column while the modifier passed to DropDownMenu is a child in that Composable.

enter image description here

You can change this position by changing offset param of DropDownMenu

offset = DpOffset(offsetX, 0.dp)

I post a sample with align end modifier in different Composables and how you can use offset by getting parent width and dropdown menu using Modifier.placed{}

@Preview
@Composable
private fun Test() {

    val density = LocalDensity.current
    var offsetX by remember {
        mutableStateOf(0.dp)
    }

    var parentWidth by remember {
        mutableStateOf(0)
    }
    Scaffold(
        modifier = Modifier.fillMaxWidth(),
        topBar = {
            Column(modifier = Modifier.fillMaxWidth().onPlaced {
                parentWidth = it.size.width
            }) {
                TopAppBar {
                    Text(text = "Text")
                }

                Text(text = "Align End", modifier = Modifier.align(Alignment.End))
                Column {
                    Text(text = "Align End in a Column", modifier = Modifier.align(Alignment.End))
                }
                DropdownMenu(
                    modifier = Modifier.onPlaced {
                        val popUpWidthPx =
                            parentWidth  - it.size.width

                        offsetX = with(density) {
                            popUpWidthPx.toDp()
                        }

                    },
                    offset = DpOffset(offsetX, 0.dp),
                    expanded = true,
                    onDismissRequest = { }
                ) {
                    DropdownMenuItem(onClick = {}) {
                        Icon(Icons.Filled.Refresh, contentDescription = null)
                    }
                    DropdownMenuItem(onClick = { }) {
                        Icon(Icons.Filled.Call, contentDescription = null)
                    }
                }
            }
        },
        content = { paddingValues: PaddingValues ->
            Column(
                modifier = Modifier
                    .padding(paddingValues)
                    .background(Color.Red)
            ) {

            }
        }
    )
}

Also source code of Dropdown menu doesn't allow adding it inside a Row with as Spacer(modifier=Modifier.weight(1f)), need to dig more source code to learn why. However as i mentioned above modifier as you can see is applied to a Column is a descendant very deep in hierarchy.

Composable
fun DropdownMenu(
    expanded: Boolean,
    onDismissRequest: () -> Unit,
    modifier: Modifier = Modifier,
    offset: DpOffset = DpOffset(0.dp, 0.dp),
    properties: PopupProperties = PopupProperties(focusable = true),
    content: @Composable ColumnScope.() -> Unit
) {
    val expandedStates = remember { MutableTransitionState(false) }
    expandedStates.targetState = expanded

    if (expandedStates.currentState || expandedStates.targetState) {
        
    
        Popup(
            onDismissRequest = onDismissRequest,
            popupPositionProvider = popupPositionProvider,
            properties = properties
        ) {
            DropdownMenuContent(
                expandedStates = expandedStates,
                transformOriginState = transformOriginState,
                //  This is the modifier we assign
                modifier = modifier,
                content = content
            )
        }
    }
}

And DropdownMenuContent

@Suppress("ModifierParameter")
@Composable
internal fun DropdownMenuContent(
    expandedStates: MutableTransitionState<Boolean>,
    transformOriginState: MutableState<TransformOrigin>,
    modifier: Modifier = Modifier,
    content: @Composable ColumnScope.() -> Unit
) {

    Card(
        modifier = Modifier.graphicsLayer {
            scaleX = scale
            scaleY = scale
            this.alpha = alpha
            transformOrigin = transformOriginState.value
        },
        elevation = MenuElevation
    ) {
        Column(
            modifier = modifier
                .padding(vertical = DropdownMenuVerticalPadding)
                .width(IntrinsicSize.Max)
                .verticalScroll(rememberScrollState()),
            content = content
        )
    }
}
Thracian
  • 43,021
  • 16
  • 133
  • 222