Flutter 颤振打开列表项上方的弹出菜单

Flutter 颤振打开列表项上方的弹出菜单,flutter,dart,flutter-plugin,Flutter,Dart,Flutter Plugin,我正在用Firestore制作一个Flitter聊天应用程序,但我被其中一个要求难住了:在聊天对话框上方显示一个反应菜单。我需要的是,当用户长按聊天文本时,反应菜单将出现在当前聊天位置的上方。类似于Facebook Messenger应用程序: 我环顾四周,发现它似乎太多了,仅仅是一个简单的功能(使弹出菜单出现在列表平铺上方,不需要动画)。我还发现了这个包:,但它不允许将小部件包装在另一个小部件上以打开reacton菜单。有没有一种简单的方法可以存档?我已经查看了PopupMenuButton

我正在用Firestore制作一个Flitter聊天应用程序,但我被其中一个要求难住了:在聊天对话框上方显示一个反应菜单。我需要的是,当用户长按聊天文本时,反应菜单将出现在当前聊天位置的上方。类似于Facebook Messenger应用程序:


我环顾四周,发现它似乎太多了,仅仅是一个简单的功能(使弹出菜单出现在列表平铺上方,不需要动画)。我还发现了这个包:,但它不允许将小部件包装在另一个小部件上以打开reacton菜单。有没有一种简单的方法可以存档?我已经查看了PopupMenuButton,但它只允许按ON键,不允许长按。

您可以使用
覆盖
小部件。我给你举个简单的例子

import 'package:flutter/material.dart';

class Temp extends StatefulWidget {
  @override
  _TempState createState() => _TempState();
}

class _TempState extends State<Temp> {
  GlobalKey floatingKey = LabeledGlobalKey("Floating");
  bool isFloatingOpen = false;
  OverlayEntry floating;

  OverlayEntry createFloating() {
    RenderBox renderBox = floatingKey.currentContext.findRenderObject();
    Offset offset = renderBox.localToGlobal(Offset.zero);
    return OverlayEntry(
      builder: (context) {
        return Positioned(
          left: offset.dx,
          width: renderBox.size.width,
          top: offset.dy - 50,
          child: Material(
            elevation: 20,
            child: Container(
              height: 50,
              color: Colors.blue,
              child: Text("I'm floating overlay")
            )
          )
        );
      }
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: RaisedButton(
          key: floatingKey,
          color: Colors.red,
          onPressed: (){
            setState(() {
              if(isFloatingOpen) floating.remove();
              else {
                floating = createFloating();
                Overlay.of(context).insert(floating);
              }
              isFloatingOpen = !isFloatingOpen;
            });
          },
        )
      ),
    );
  }
}
导入“包装:颤振/材料.省道”;
类Temp扩展StatefulWidget{
@凌驾
_TempState createState()=>u TempState();
}
类_TempState扩展了状态{
GlobalKey floatingKey=LabeledGlobalKey(“浮动”);
bool isFloatingOpen=false;
上入口浮动;
OverlayEntry createFloating(){
RenderBox RenderBox=floatingKey.currentContext.finderObject();
Offset Offset=renderBox.localToGlobal(Offset.zero);
返回重叠入口(
生成器:(上下文){
返回定位(
左:offset.dx,
宽度:renderBox.size.width,
顶部:offset.dy-50,
儿童:材料(
海拔:20,
子:容器(
身高:50,
颜色:颜色,蓝色,
子:文本(“我在浮动覆盖”)
)
)
);
}
);
}
@凌驾
小部件构建(构建上下文){
返回脚手架(
正文:中(
孩子:升起按钮(
键:floatingKey,
颜色:颜色,红色,
已按下:(){
设置状态(){
如果(isFloatingOpen)浮动。删除();
否则{
floating=createFloating();
覆盖.of(上下文).插入(浮动);
}
isFloatingOpen=!isFloatingOpen;
});
},
)
),
);
}
}

我认为在这个布局上最好使用覆盖小部件:````谢谢你的建议,我尝试了你的例子,它与我正在寻找的非常相似。一个问题是,是否有一种方法可以在按下outside键时关闭覆盖,而不仅仅是在单击按钮时关闭覆盖?这对于ListView又是如何工作的?
isFloatingOpen
只是管理覆盖层打开和关闭状态的一个变量。您可以使用GestureDetector包装整个脚手架,并在覆盖层打开时使用onTap关闭覆盖层。是的,它可以与ListView一起工作,我以前试过。顺便说一句,如果我的答案有用的话,可以用upvote吗?抱歉,我正在尝试收集声誉hahaSo如何为每个列表项分配浮动键?假设我有一个来自数据源的100个项目的列表,并使用ListView.builder将其构建到ListView中,我是否必须创建100个不同的
floatingKey
来分配给每个ListItem?您可以为数据创建模型类,以便每个数据都有自己的键。