如何在颤动中在按下/手指/鼠标/光标位置显示菜单

Art*_*ine 11 dart flutter flutter-layout

我有这段代码是从Style clipboard in flutter 中得到的

showMenu(
        context: context,
        // TODO: Position dynamically based on cursor or textfield
        position: RelativeRect.fromLTRB(0.0, 600.0, 300.0, 0.0),
        items: [
          PopupMenuItem(
            child: Row(
              children: <Widget>[
                // TODO: Dynamic items / handle click
                PopupMenuItem(
                  child: Text(
                    "Paste",
                    style: Theme.of(context)
                        .textTheme
                        .body2
                        .copyWith(color: Colors.red),
                  ),
                ),
                PopupMenuItem(
                  child: Text("Select All"),
                ),
              ],
            ),
          ),
        ],
      );
Run Code Online (Sandbox Code Playgroud)

这段代码效果很好,除了创建的弹出窗口位于固定位置之外,我将如何使它在鼠标/按下/手指/光标位置或附近的某个位置弹出,有点像你想要的时候复制并粘贴到您的手机上。(此对话框弹出不会用于复制和粘贴)

Era*_*ore 11

我能够通过使用这个答案解决类似的问题:https : //stackoverflow.com/a/54714628/559525

基本上,我在每个 ListTile 周围添加了一个 GestureDetector(),然后你使用 onTapDown 来存储你的按下位置和 onLongPress 来调用你的 showMenu 函数。以下是我添加的关键功能:

  _showPopupMenu() async {
    final RenderBox overlay = Overlay.of(context).context.findRenderObject();

    await showMenu(
      context: context,
      position: RelativeRect.fromRect(
          _tapPosition & Size(40, 40), // smaller rect, the touch area
          Offset.zero & overlay.size // Bigger rect, the entire screen
          ),
      items: [
        PopupMenuItem(
          child: Text("Show Usage"),
        ),
        PopupMenuItem(
          child: Text("Delete"),
        ),
      ],
      elevation: 8.0,
    );
  }

  void _storePosition(TapDownDetails details) {
    _tapPosition = details.globalPosition;
  }
}
Run Code Online (Sandbox Code Playgroud)

然后这里是完整的代码(你必须调整一些东西,比如图像,并填写设备列表):

import 'package:flutter/material.dart';
import 'package:auto_size_text/auto_size_text.dart';
import 'dart:core';

class RecentsPage extends StatefulWidget {
  RecentsPage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _RecentsPageState createState() => _RecentsPageState();
}

class _RecentsPageState extends State<RecentsPage> {

  List<String> _recents;

  var _tapPosition;

  @override
  void initState() {
    super.initState();
    _tapPosition = Offset(0.0, 0.0);
    getRecents().then((value) {
      setState(() {
        _recents = value;
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Color(0xFFFFFFFF),
      body: SafeArea(
        child: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.start,
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: <Widget>[
              Container(height: 25),
              Stack(
                children: <Widget>[
                  Container(
                    padding: EdgeInsets.only(left: 40),
                    child: Center(
                      child: AutoSizeText(
                        "Recents",
                        maxLines: 1,
                        textAlign: TextAlign.center,
                        style: TextStyle(fontSize: 32),
                      ),
                    ),
                  ),
                  Container(
                    padding: EdgeInsets.only(left: 30, top: 0),
                    child: GestureDetector(
                        onTap: () => Navigator.of(context).pop(),
                        child: Transform.scale(
                          scale: 2.0,
                          child: Icon(
                            Icons.chevron_left,
                          ),
                        )),
                  ),
                ],
              ),
              Container(
                height: 15,
              ),
              Container(
                height: 2,
                color: Colors.blue,
              ),
              Container(
                height: 10,
              ),
              Flexible(
                child: ListView(
                  padding: EdgeInsets.all(15.0),
                  children: ListTile.divideTiles(
                    context: context,
                    tiles: _getRecentTiles(),
                  ).toList(),
                ),
              ),
              Container(height: 15),
            ],
          ),
        ),
      ),
    );
  }

  List<Widget> _getRecentTiles() {
    List<Widget> devices = List<Widget>();
    String _dev;
    String _owner = "John Doe";

    if (_recents != null) {
      for (_dev in _recents.reversed) {
        if (_dev != null) {
          _dev = _dev.toUpperCase().trim();

            String serial = "12341234";

            devices.add(GestureDetector(
                onTapDown: _storePosition,
                onLongPress: () {
                  print("long press of $serial");
                  _showPopupMenu();
                },
                child: ListTile(
                  contentPadding: EdgeInsets.symmetric(vertical: 20),
                  leading: Transform.scale(
                      scale: 0.8,
                      child: Image(
                        image: _myImage,
                      )),
                  title: AutoSizeText(
                    "$_owner",
                    maxLines: 1,
                    style: TextStyle(fontSize: 22),
                  ),
                  subtitle: Text("Serial #: $serial"),
                  trailing: Icon(Icons.keyboard_arrow_right),
                )));
        }
      }
    } else {
      devices.add(ListTile(
        contentPadding: EdgeInsets.symmetric(vertical: 20),
        title: AutoSizeText(
          "No Recent Devices",
          maxLines: 1,
          style: TextStyle(fontSize: 20),
        ),
        subtitle:
            Text("Click the button to add a device"),
        onTap: () {
          print('add device');
        },
      ));
    }
    return devices;
  }

  _showPopupMenu() async {
    final RenderBox overlay = Overlay.of(context).context.findRenderObject();

    await showMenu(
      context: context,
      position: RelativeRect.fromRect(
          _tapPosition & Size(40, 40), // smaller rect, the touch area
          Offset.zero & overlay.size // Bigger rect, the entire screen
          ),
      items: [
        PopupMenuItem(
          child: Text("Show Usage"),
        ),
        PopupMenuItem(
          child: Text("Delete"),
        ),
      ],
      elevation: 8.0,
    );
  }

  void _storePosition(TapDownDetails details) {
    _tapPosition = details.globalPosition;
  }
}
Run Code Online (Sandbox Code Playgroud)


Sam*_*ain 5

在此输入图像描述

像这样使用手势检测器的 onTapDown

 GestureDetector(
        onTapDown: (TapDownDetails details) {
          showPopUpMenu(details.globalPosition);
        },
Run Code Online (Sandbox Code Playgroud)

然后在这个方法中我们使用点击详细信息来查找位置

Future<void> showPopUpMenu(Offset globalPosition) async {
double left = globalPosition.dx;
double top = globalPosition.dy;
await showMenu(
  color: Colors.white,
  //add your color
  context: context,
  position: RelativeRect.fromLTRB(left, top, 0, 0),
  items: [
    PopupMenuItem(
      value: 1,
      child: Padding(
        padding: const EdgeInsets.only(left: 0, right: 40),
        child: Row(
          children: [
            Icon(Icons.mail_outline),
            SizedBox(
              width: 10,
            ),
            Text(
              "Menu 1",
              style: TextStyle(color: Colors.black),
            ),
          ],
        ),
      ),
    ),
    PopupMenuItem(
      value: 2,
      child: Padding(
        padding: const EdgeInsets.only(left: 0, right: 40),
        child: Row(
          children: [
            Icon(Icons.vpn_key),
            SizedBox(
              width: 10,
            ),
            Text(
              "Menu 2",
              style: TextStyle(color: Colors.black),
            ),
          ],
        ),
      ),
    ),
    PopupMenuItem(
      value: 3,
      child: Row(
        children: [
          Icon(Icons.power_settings_new_sharp),
          SizedBox(
            width: 10,
          ),
          Text(
            "Menu 3",
            style: TextStyle(color: Colors.black),
          ),
        ],
      ),
    ),
  ],
  elevation: 8.0,
).then((value) {
  print(value);
  if (value == 1) {
    //do your task here for menu 1
  }
  if (value == 2) {
    //do your task here for menu 2
  }
  if (value == 3) {
    //do your task here for menu 3
  }
});
Run Code Online (Sandbox Code Playgroud)

希望它有效

  • 为我工作,只需在函数上添加上下文属性。 (2认同)