I have a listview with a few itens (i.e. 15). This listview doesn’t have an object attached to it. It’s a simple list view with a array of list tiles.
When user long presses an item, it shows a popup menu next to the item, and it should allow doing some stuff with the data from that specific ListTile. The problem is I can’t find a way to get a reference to the ListTile menu was called from.
After searching, all examples I find seem like a hack or “workaround” to find the right tile.
For example, you can have a listview.builder, where you have an List<> object previously initialized, and you pass that object to the listview.builder. From there, you “find” the position using the index.
But can’t I find the right widget from where menu was called from?
For example, with some property like an owner, a caller, a parent, or whatever the name is for the parent widget where the menu was called from.
Consider the following example StatelessWidget (two itens only):
enter image description here
Code below.
import 'package:flutter/material.dart';
class ListViewMenuClick extends StatelessWidget {
const ListViewMenuClick({super.key});
@override
Widget build(BuildContext context) {
final List<PopupMenuEntry<String>> items = [];
items.addAll([
PopupMenuItem(
value: 'Title',
child: Text('Title'),
onTap: () {},
),
PopupMenuItem(
value: 'Subtitle',
child: Text('Subtitle'),
),
]);
Offset position = Offset(0, 0);
return SafeArea(
child: Scaffold(
appBar: AppBar(
centerTitle: true,
title: Text(
runtimeType.toString(),
),
),
body: Scrollbar(
thickness: 8,
interactive: true,
child: ListView(
children: [
GestureDetector(
onTapDown: (details) {
position = details.globalPosition; //Get position of click to show popup menu at the correct place
},
child: ListTile(
onLongPress: () {
showMenu(
context: context,
position: RelativeRect.fromLTRB(position.dx, position.dy, 0, 0), //Sets position for menu
items: items,
).then(
(value) {
if (value != null && context.mounted) {
String message = "";
switch (value) {
case 'Title':
{
message =
"Menu item is $value, List tile title is ????????????????"; //this is where we should get the title
}
case 'Subtitle':
{
message =
"Menu item is $value, List tile subtitle is ????????????????"; //this is where we should get the subtitle
}
break;
default:
}
return ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
backgroundColor: Color.fromARGB(0x7f, 0, 0, 0),
behavior: SnackBarBehavior.floating,
content: Text(message),
),
);
} else {
return SnackBar(content: Text("No value"));
}
},
).onError(
(error, stackTrace) {
return SnackBar(content: Text("Error: ${error.toString()}"));
},
);
},
tileColor: Colors.black12,
title: Text("MY TITLE IS ABC"),
subtitle: Text("MY SUBTITLE IS XYZ"),
),
),
GestureDetector(
onTapDown: (details) {
position = details.globalPosition; //Get position of click to show popup menu at the correct place
},
child: ListTile(
onLongPress: () {
showMenu(
context: context,
position: RelativeRect.fromLTRB(position.dx, position.dy, 0, 0), //Sets position for menu
items: items,
).then(
(value) {
if (value != null && context.mounted) {
String message = "";
switch (value) {
case 'Title':
{
message =
"Menu item is $value, List tile title is ????????????????"; //this is where we should get the title
}
case 'Subtitle':
{
message =
"Menu item is $value, List tile subtitle is ????????????????"; //this is where we should get the subtitle
}
break;
default:
}
return ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
backgroundColor: Color.fromARGB(0x7f, 0, 0, 0),
behavior: SnackBarBehavior.floating,
content: Text(message),
),
);
} else {
return SnackBar(content: Text("No value"));
}
},
).onError(
(error, stackTrace) {
return SnackBar(content: Text("Error: ${error.toString()}"));
},
);
},
tileColor: Colors.white,
title: Text("YOU CAN'T GET MY TITLE FROM POPUP MENU"),
subtitle: Text("NOR MY SUBTITLE"),
),
),
],
),
),
),
);
}
}
A have a ListTile (), and inside it, the showMenu() is called to show the popup menu.
Now take a look at switch statament: Isn’t there a way to get a reference to that exact ListTile, assuming the menu was called INSIDE it?
Notice my question isn’t about an alternative way to do it.
What I want to know is how (if possible at all) I can get a reference to the ListTile that user long clicked when the menu item is clicked, so that I can access its properties (like title and subtitle) in some way.
I’ve tried searching in different places, but every example either don’t explain how to handle the menu click using tile data, or it points to the ListView.builder() (as I explained before).
Smith Onion is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.