What is the event that is triggered from PopupMenuButton or any other approach, so that when in the example code attached, when user opens the pop-up menu from the right side of items, does sets the selectedIndex to the row number of the ListView?
Basically, when a user opens the popup menu, I want to select the row, but currently when the popup is opened, it does not even get fired that I can use to set the value. The onTap does not get executed till the row is selected.
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: HomePage(),
);
}
}
class HomePage extends StatefulWidget {
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
final GlobalKey<ScaffoldState> _scaffoldkey = new GlobalKey<ScaffoldState>();
final List<String> _names = [
'Liam', 'Noah', 'Oliver', 'William', 'Elijah',
];
int selectedIndex = -1 ;
@override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldkey,
appBar: AppBar(
title: Text('Pop Menu with List'),
),
body: ListView.builder(
itemBuilder: (_, i) {
String name = _names[i];
return ListTile(
title: (selectedIndex == i) ? Text('$name', style: TextStyle(fontWeight: FontWeight.bold),) : Text('$name'),
onTap: () {
setState(() {
selectedIndex = i;
});
},
trailing: PopupMenuButton(
icon: Icon(Icons.more_vert),
itemBuilder: (context) {
return [
PopupMenuItem(
value: 'edit',
child: Text('Edit'),
),
PopupMenuItem(
value: 'delete',
child: Text('Delete'),
)
];
},
onSelected: (String value) => actionPopUpItemSelected(value, name),
),
);
},
itemCount: _names.length,
),
);
}
void actionPopUpItemSelected(String value, String name) {
// _scaffoldkey.currentState.hideCurrentSnackBar();
ScaffoldMessenger.of(context).hideCurrentSnackBar;
String message;
if (value == 'edit') {
message = 'You selected edit for $name';
} else if (value == 'delete') {
message = 'You selected delete for $name';
} else {
message = 'Not implemented';
}
final snackBar = SnackBar(content: Text(message));
// _scaffoldkey.currentState.showSnackBar(snackBar);
ScaffoldMessenger.of(context).showSnackBar(snackBar);
}
}
The sample code is adapted from Flutter: Pop up menu list view.
Try using the gesture detector with the showMenu
method.
I used Inkwell and Ink here to give a more natural button feel, but it’s the same functionality.
body: ListView.builder(
itemBuilder: (_, i) {
String name = _names[i];
return ListTile(
title: (selectedIndex == i)
? Text(
'$name',
style: TextStyle(fontWeight: FontWeight.bold),
)
: Text('$name'),
trailing: InkWell(
customBorder: CircleBorder(),
child: Ink(
padding: const EdgeInsets.all(2),
child: Icon(Icons.more_vert)),
onTapDown: (details) async {
setState(() {
selectedIndex = i;
});
final RenderBox overlay = Overlay.of(context)!
.context
.findRenderObject() as RenderBox;
await showMenu(
context: context,
position: RelativeRect.fromRect(
details.globalPosition & const Size(40, 40),
Offset.zero & overlay.size),
items: const [
PopupMenuItem(
value: 'edit',
child: Text('Edit'),
),
PopupMenuItem(
value: 'delete',
child: Text('Delete'),
)
],
elevation: 8.0,
).then((String? v) => actionPopUpItemSelected(v!, name));
},
),
);
},
itemCount: _names.length,
),