PopupMenuButton 的事件在 flutter 中打开(激活)

问题描述 投票:0回答:1

从 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

flutter popup popupmenu
1个回答
1
投票

尝试通过

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,
  ),
© www.soinside.com 2019 - 2024. All rights reserved.