从 PopupMenuButton 或任何其他方法触发的事件是什么,以便在附加的示例代码中,当用户从项目右侧打开弹出菜单时,确实将 selectedIndex 设置为 ListView 的行号?
基本上,当用户打开弹出菜单时,我想选择该行,但当前打开弹出菜单时,它甚至不会被触发,我可以用它来设置值。在选择该行之前,onTap 不会执行。
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);
}
}
示例代码改编自flutter-pop-up-menu-list-view。
尝试通过
showMenu
方法使用手势检测器。
我在这里使用 Inkwell 和 Ink 来提供更自然的按钮感觉,但功能相同。
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,
),