1,实现效果:

在这里插入图片描述

2,关键代码:

//1.定义一个全局key
GlobalKey anchorKey = GlobalKey();

Text( 
    'context',
    key:anchorKey // 2.绑定key
);

//3. 获取到当前context
var renderBox = anchorKey.currentContext?.findRenderObject() as RenderBox;
//4. 获取到当前dom元素坐标
var offset = renderBox.globalToLocal(Offset(100, renderBox.size.height));

3.完整代码

import 'package:flutter/material.dart';

class AskQuestionPage extends StatefulWidget {
  @override
  State createState() => _AskQuestionPageState();
}

class _AskQuestionPageState extends State {
  //定义一个全局key (关键代码!!)
  GlobalKey anchorKey = GlobalKey();
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        SizedBox(
          height: 100,
        ),
        GestureDetector(
          child: Container(
            child: Text(
              '长按这里弹出弹窗',
              style: TextStyle(backgroundColor: Colors.amber, fontSize: 15),
              key: anchorKey,// 绑定key(关键代码!!)
            ),
          ),
          onLongPressStart: (detail) {
            setState(() {});
            _showMenu(context, detail);
          },
        )
      ],
    );
  }

  PopupMenuButton _popMenu() {
    return PopupMenuButton(
      itemBuilder: (context) => _getPopupMenu(context),
      onSelected: (dynamic value) {
        print('onSelected$value');
        _selectValueChange(value);
      },
      onCanceled: () {
        print('取消');
        setState(() {});
      },
    );
  }

  _selectValueChange(String value) {
    setState(() {});
  }

  _showMenu(BuildContext context, LongPressStartDetails detail) {
    // 获取到当前context(关键代码!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!)
    var renderBox = anchorKey.currentContext?.findRenderObject() as RenderBox;
    // 获取到当前dom元素坐标(关键代码!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!)
    var offset = renderBox.globalToLocal(Offset(100, renderBox.size.height));
    final position = RelativeRect.fromLTRB(
        detail.globalPosition.dx, //取点击位置坐弹出x坐标
        offset.dy, //取demo高度做弹出y坐标(这样弹出就不会遮挡文本)
        detail.globalPosition.dx,
        offset.dy);
    var pop = _popMenu();
    showMenu(
      context: context,
      items: pop.itemBuilder(context),
      position: position, //弹出框位置
    ).then((dynamic newValue) {
      if (!mounted) return null;
      if (newValue == null) {
        if (pop.onCanceled != null) pop.onCanceled!();
        return null;
      }
      if (pop.onSelected != null) pop.onSelected!(newValue);
    });
  }

  _getPopupMenu(BuildContext context) {
    return [
      PopupMenuItem(
        value: '举报',
        child: Text('举报'),
      ),
    ];
  }
}

参考来源:
1.点击位置弹出菜单栏(仿微信文本长按位置下方弹出菜单)
2.Get “y” position of container on Flutter

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐