Overlay Model

you can find the example below in example/overlay_model_example.dart.

without this library, this is how we create overlay by OverlayEntry and OverlayState:

class _SampleState extends State<Sample> {
  Widget buildOverlay(BuildContext context) =>
      Center(
        child: SizedBox.square(
          dimension: 100,
          child: ColoredBox(
            color: Colors.red.shade200,
            child: TextButton(
              onPressed: _toggle,
              child: Text('remove overlay'),
            ),
          ),
        ),
      );

  OverlayEntry? entry;

  void _toggle() {
    OverlayEntry? entry = this.entry;
    if (entry == null) {
      entry = OverlayEntry(builder: buildOverlay);
      this.entry = entry;
      Overlay.of(context).insert(entry);
      return;
    }
    entry.remove();
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: TextButton(
        onPressed: _toggle,
        child: Text('insert new overlay'),
      ),
    );
  }
}

with this library, we can create overlay by a mixin without holding OverlayEntry instance:

class _SampleState extends State<Sample> with OverlayMixin<Sample> {
  // ...
  void _toggle() =>
      overlays.isEmpty
          ? overlayInsert(
        OverlayPlan(
          isRemovable: true,
          isUpdatable: false,
          builder: buildOverlay,
        ),
      )
          : overlays.first.remove();

// ...
}

Not only we don't have to create an overlay entry instance, but we also have more control on overlay insertion, update, removal by OverlayPlan and OverlayModel.\n Not just OverlayMixin, there are also OverlayFutureMixin and OverlayStreamMixin !

take OverlayFutureMixin for example:

class _SampleState extends State<Sample> with OverlayMixin<Sample>, OverlayFutureMixin<Sample> {
  void toggle() =>
      overlayWaitingFuture(
        future: Future.delayed(Duration(seconds: 1)),
        plan: OverlayPlan(
          isRemovable: true,
          builder: buildOverlay,
        ),
        after: (model) {
          if (overlays.isEmpty) return;
          model.remove();
          ScaffoldMessenger.of(context).showSnackBar(
            SnackBar(content: Text('overlay is removed after future')),
          );
        },
      );

  Widget buildOverlay(BuildContext context) =>
      Center(
        child: SizedBox.square(
          dimension: 50,
          child: CircularProgressIndicator(),
        ),
      );
// ...
}

take OverlayStreamMixin for example:

class _SampleState extends State<Sample>
    with OverlayMixin<Sample>, OverlayFutureMixin<Sample>, OverlayStreamMixin<Sample> {
  Stream<int> stream() async* {
    for (var i = 0; i < 6; i++) {
      yield i;
      await Future.delayed(Duration(milliseconds: 2500));
    }
  }

  void toggle() =>
      overlayListenStream(
        stream: stream(),
        planFor: (data) {
          if (data % 2 == 0) {
            ScaffoldMessenger.of(context).showSnackBar(
              SnackBar(
                content: Text('received $data and insert overlay'),
                duration: Duration(seconds: 1),
              ),
            );
            return OverlayPlan.model(
              isRemovable: true,
              builder: (context, model) => buildOverlay(context, model, data),
            );
          }
          overlays.first.remove();
          ScaffoldMessenger.of(context).showSnackBar(
            SnackBar(
              content: Text('previous overlay is removed'),
              duration: Duration(seconds: 1),
            ),
          );
          return null;
        },
      );

  Widget buildOverlay(BuildContext context, OverlayModel model, int data) =>
      Center(
        child: SizedBox.square(
          dimension: 50,
          child: Material(
            textStyle: TextStyle(color: Colors.red),
            shape: CircleBorder(side: BorderSide(color: Colors.black)),
            child: Center(child: Text('data: $data')),
          ),
        ),
      );
// ...
}

see the comment above lib/overlay_model.dart to understand how it works ! hopes you have fun in programming !

Libraries

overlay_model