本文主要介绍Flutter Overlay 用法简介。

Overlay 基本用法

Overlay 实际上是一个 Stack,所以 OverlayEntry 的内容可以是 Positioned

var overlayEntry = OverlayEntry(builder: (context) => Positioned(...););
Overlay.of(context).insert(overlayEntry);
  • 显示 Overlay - 使用 Overlay.of(context).insert() 方法
  • 隐藏 Overlay - 使用 overlayEntry.remove() 方法

overlay-basic

Overlay 高级用法

指定位置

有时我们想指定 Overlay 的显示位置,实现方式如下:

  • 先使用 BuildContext.findRenderObject() 来找到当前 Widget 对应的 RenderObject
  • 再使用 RenderBox.localToGlobal() 找到 Widget 在屏幕上的位置

具体见 _calcPos() 方法。

class _MyButton extends StatefulWidget {
  final PosCallback callback;

  const _MyButton({Key key, this.callback}) : super(key: key);

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

class __MyButtonState extends State<_MyButton> {
  List<double> _calcPos() {
    RenderBox renderBox = context.findRenderObject();
    var size = renderBox.size;
    var offset = renderBox.localToGlobal(Offset.zero);

    return [offset.dx, offset.dy + size.height];
  }

  @override
  Widget build(BuildContext context) {
    return RaisedButton(
      onPressed: () {
        List<double> list = _calcPos();
        widget.callback(list[0], list[1]);
      },
      child: Text('show overlay'),
    );
  }
}

overlay-pos

跟随滚动

使用 LayerLink 来让 Overlay 跟随指定的 Widget 来滚动。

代码篇幅较长,这里就不贴上来了。完整代码见 gist

overlay-scroll

参考