Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 394 Vote(s) - 3.4 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Jetpack compose popup menu

#1
I am trying to rewrite my project UI using Jetpack compose. Any idea to add popup menu using jetpack compose in android?. like this one below.

[![like this one][1]][1]

I tried to implement it using Stack() layout but the results are not up to the mark.


@Composable
fun LiveDataComponentList(productList: List<Product>) {
AdapterList(data = productList) { product ->
Stack() {
Clickable(onClick = { PopupState.toggleOwner(product) }) {
Card(...) {...}

if (PopupState.owner == product) {
Surface(color = Color.Gray,modifier = Modifier.gravity(Alignment.TopEnd) + Modifier.padding(12.dp)) {
Column() {
Text("menu 1")
Text("menu 2")
Text("menu 3")
Text("menu 4")
Text("menu 5")
}
}
}
}
}
}

and PopupState is

@Model
object PopupState
{
var owner:Product?=null
fun toggleOwner(item:Product)
{
if(owner==item)
owner=null
else
owner=item
}
}

result is

[screenshot][2]


[1]:

[2]:
Reply

#2
After some research I found a solution to this, the key component is **DropdownPopup**


@Composable
fun LiveDataComponentList(productList: List<Product>) {
AdapterList(data = productList) { product ->


Clickable(onClick = { PopupState.toggleOwner(product) }) {
Card(...) {...}
}
if (PopupState.owner == product) {
DropdownPopup(dropDownAlignment = DropDownAlignment.End)
{

Surface(
shape = RoundedCornerShape(4.dp),
elevation = 16.dp,
color = Color.White,
modifier = Modifier.gravity(Alignment.End)+ Modifier.padding(end = 10.dp)
)
{
Column(modifier = Modifier.padding(10.dp)) {

MenuItem(text ="Edit", onClick = {})
MenuItem(text = "Delete", onClick = {})
MenuItem(text = "Details", onClick = {})


}
}
}
}


}
}

@Composable
fun MenuItem(text: String, onClick: () -> Unit) {
Clickable(onClick = onClick, modifier = Modifier.padding(6.dp)) {
Text(text = text, style = MaterialTheme.typography.subtitle1)

}
}

This solution works fine with compose version **dev10**
Reply

#3
Since DropDownPopup was removed, I implemented one using [DropDownMenu](

[To see links please register here]

) instead like this:

PopupMenu:
```
@Composable
fun PopupMenu(
menuItems: List<String>,
onClickCallbacks: List<() -> Unit>,
showMenu: Boolean,
onDismiss: () -> Unit,
toggle: @Composable () -> Unit,
) {
DropdownMenu(
toggle = toggle,
expanded = showMenu,
onDismissRequest = { onDismiss() },
) {
menuItems.forEachIndexed { index, item ->
DropdownMenuItem(onClick = {
onDismiss()
onClickCallbacks[index]
}) {
Text(text = item)
}
}
}
}
```

Toggle (thing to long click on to trigger PopupMenu):

```
@Preview
@Composable
fun Toggle() {
var showMenu by remember { mutableStateOf(false) }

PopupMenu(
menuItems = listOf("Delete"),
onClickCallbacks = listOf { println("Deleted") },
showMenu = showMenu,
onDismiss = { showMenu = false }) {
Text(
modifier = Modifier.clickable(onClick = {}, onLongClick = {
showMenu = true
}),
text = "Long click here",
)
}
}
```
Reply

#4
For My use case I created a Icon button which has pop up menu and that can be used where pop menu is needed.

@Composable
fun PopUpMenuButton(
options: List<PopUpMenuItem>,
action: (String) -> Unit,
iconTint: Color = Color.Black,
modifier: Modifier
) {

var expanded by remember { mutableStateOf(false) }

Column {

Box(modifier = Modifier.size(24.dp)) {
IconButton(onClick = {
expanded = !expanded
}) {
Icon(
painter = painterResource(id = R.drawable.ic_dots),
contentDescription = null,
modifier = Modifier.wrapContentSize(),
tint = iconTint
)
}
}

Box(modifier = modifier) {
DropdownMenu(
expanded = expanded,
onDismissRequest = { expanded = false },
modifier = Modifier
.widthIn(min = 120.dp, max = 240.dp)
.background(MaterialTheme.colors.background)
) {
options.forEachIndexed { _, item ->
DropdownMenuItem(onClick = {
expanded = false
action(item.id)
}) {
Row(
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically,
) {
Icon(
painterResource(id = item.icon),
contentDescription = null,
tint = iconTint,
)
Spacer(modifier = Modifier.width(8.dp))
Text(
text = item.label,
style = MaterialTheme.typography.body1,
overflow = TextOverflow.Ellipsis
)
}
}
if (item.hasBottomDivider) {
Divider()
}
}
}
}
}

}

Then I created a simple data class for defining menu item

data class PopUpMenuItem(
val id: String,
val label: String,
val icon: Int,
val hasBottomDivider: Boolean = false,
)

Then at the calling side I simply use this button like this

PopUpMenuButton(
modifier = Modifier.wrapContentSize(),
options = PopMenuOptionsProvider.sectionCardMenu,
iconTint = MaterialTheme.extendedColor.regularGray,
action = { menuId -> onSectionMenuAction(menuId) }
)

It can be further refactored to make it more extensible, but this worked for me.
Reply

#5
You can use the [**`DropdownMenu`**][1].

Something like:

var expanded by remember { mutableStateOf(false) }

DropdownMenu(
expanded = expanded,
onDismissRequest = { expanded = false }
) {
DropdownMenuItem(
text = { Text("Refresh") },
onClick = { /* Handle refresh! */ }
)
DropdownMenuItem(
text = { Text("Settings") },
onClick = { /* Handle settings! */ }
)
Divider()
DropdownMenuItem(
text = { Text("Send Feedback") },
onClick = { /* Handle send feedback! */ }
)
}

It works with M3. With M2 you have to use:

androidx.compose.material.DropdownMenuItem(
onClick = { expanded = false }
) {
Text("All Accounts")
}

[![enter image description here][2]][2]

About the position, as explained in the documentation:

> A `DropdownMenu` behaves similarly to a `Popup`, and will use the position of the parent layout to position itself on screen. **Commonly a `DropdownMenu` will be placed in a **`Box`** with a sibling that will be used as the 'anchor'**.

Example:

Box(
modifier = Modifier.fillMaxSize().wrapContentSize(Alignment.TopStart)
){
IconButton(onClick = { expanded = true }) {
Icon(
Icons.Default.MoreVert,
contentDescription = "Localized description"
)
}
DropdownMenu(
expanded = expanded,
onDismissRequest = { expanded = false }
) {
//...
}

[1]:

[To see links please register here]

[2]:
Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through