实现的时候碰到的几个问题:

  1. 实现方式:
  • 如果用Navigator路由到新页,可以用PopupRoute自己实现,也可以直接用PageRouteBuilder来自定义,只要opaque设置为false就可以实现透明背景的弹出效果。同时可以方便的将barrierDismissible设置为true实现点击消失。其实PopupRoute其实也就是通过这两个属性来设置的 。
  • 如果实现浮窗效果,可以使用Overlay、OverlayEntry来实现,这种本质上是在build常规层之后,启动一个特殊的build过程,将Overlay层渲染到常规层之上。可以实现弹出层之外透明部分可将点击下层的效果。
  1. 弹出菜单总是要决定自己的位置,一般是触发事件的控件之上或之下,可以使用CustomSingleChildLayout来实现,delegate接收到getPositionForChild事件,可以获取child的大小,返回一个Offset就可以决定位置。
  2. 本来不想由外部定义或内部写死菜单的长度,由元素大小自动决定。这样就有两种实现方式,暂时都碰到了问题,记录一下。后续看看怎么实现好一点
  • 内部大小使用Wrap来当容器,这样按钮如果太多溢出,会自动换行,但一个是不太好看,上下行按钮个数容易不对称,且多行按钮体验就不好,也没有回调来判断是否自动换行,换行的话每行按钮的个数。如果可以在渲染前就知道按钮大小,则可以较为简单的进行绘制与排布,但Flutter中没有好的实现,网上也只有Text的大小提前获取方式——通过提前创建未显示的控件来获取大小。
  • 使用Row来当容器,会有溢出的问题,和上面的问题一样,如果可以提前获得子控件大小,则可以通过控制显示按钮的数量来处理。
  1. 要在build后处理事件,可以在WidgetsBinding.instance.addPostFrameCallback中添加,如页面显示后立即显示Dialog,在initState是不行的,因为正在build过程中,此时就可以在上述回调中添加。这个事件在帧绘制完成后立即调用,请不要在此函数中再次触发build。