With the expansion and extension of business, the need for a variety of functions, and the same effect can have a variety of implementation schemes; Today we will learn how to implement basic hover guidance effects using Overlay.

Overlay manages the storage of individual items in a floating layer (last in, first out); Overlay the source code is also a Stack layer that uses overentries to Overlay one by one, The OverEntry can define its position in the Overlay using either Positioned tourists or animatedtourists;

When the MaterialApp is created, it automatically creates a Navigator, then an Overlay, and then uses the Navigator to manage the interface in the route;

Source code analysis

const Overlay({
    Key key,
    this.initialEntries = const <OverlayEntry>[],
})

class OverlayEntry 
  OverlayEntry({
    @required this.builder,
    bool opaque = false,
    bool maintainState = false,
  })
}
Copy the code

According to source code analysis, overlays are mainly composed of OverlayEntry floating layer elements and are stored in the form of stacks. Opaque: Indicates whether the current float element covers the entire Overlay float layer. MaintainState Is used with Opaque. MaintainState specifies whether to add opaque float elements to the Widget Tree.

Case try

Β Β Β Β Β Β OverlayAs a floating layer of application effect is very wide, many teachers have passed onlineOverlayImplement customizationToast / Dialog / PopupMenu / List itemAnd so on, but small dishes try to passOverlayTo achieve novice guidance in the upgrade process; Β Β Β Β Β Β OverlayMainly throughinsert / insertAllWay to joinOverEntryFloat element, throughremoveRemove float element

insert One OverEnrty

If you want to show just one OverEntry float element, you can add it to the Overlay by insert, or you can add an array with just one OverEntry by insertAll. Finally, remove closes the float element. Note that all elements in the array must be removed.

// insert overlayEntry = OverlayEntry(builder: (context) { return Stack(children: <Widget>[Positioned( top: (height-200) * 0.5, left: (width-200) * 0.5, child: GestureDetector(onTap: () => overlayEntry. Remove (), child: _itemContainer (Colors. Blue. WithOpacity (0.6))))); }); Overlay.of(context).insert(overlayEntry);Copy the code

// insertAll overlayEntry = OverlayEntry(builder: (context) { return Stack(children: <Widget>[Positioned( top: (height-200) * 0.5, left: (width-200) * 0.5, child: GestureDetector(onTap: () {overlayentry.remove (); overlayentrylist.clear ();}, child: _itemContainer(colors.brown.withopacity (0.6)))))); }); overlayEntryList.add(overlayEntry); Overlay.of(context).insertAll(overlayEntryList);Copy the code

insert Three OverEntrys

If multiple OverEntry float elements need to be displayed, insertAll can only be used to add to the Overlay, which is added in stacks by default. InsertAll adds all of the overentries to the Overlay at once.

overlayEntryList.add(OverlayEntry(builder: (context) { return Stack(children: <Widget>[ Positioned(top: (height-200) * 0.5-50, left: (width-200) * 0.5-50, Child: GestureDetector(onTap: () { --overIndex; overlayEntryList[overIndex].remove(); overlayEntryList.removeLast(); }, child: _itemContainer (Colors. Red. WithOpacity (0.6))))); })); overlayEntryList.add(OverlayEntry(builder: (context) { return Stack(children: <Widget>[ Positioned(top: (height-200) * 0.5, left: (width-200) * 0.5, child: GestureDetector(onTap: () { --overIndex; overlayEntryList[overIndex].remove(); overlayEntryList.removeLast(); }, child: _itemContainer (Colors. Orange. WithOpacity (0.6))))); })); overlayEntryList.add(OverlayEntry(builder: (context) { return Stack(children: <Widget>[ Positioned(top: (height-200) * 0.5 + 50, left: (width -200) * 0.5 + 50, child: GestureDetector(onTap: () { --overIndex; overlayEntryList[overIndex].remove(); overlayEntryList.removeLast(); }, child: _itemContainer (Colors. Blue. WithOpacity (0.6))))); })); overIndex = overlayEntryList.length; Overlay.of(context).insertAll(overlayEntryList);Copy the code

If you need to show more than oneOverlayEntryNew ones can be added separately in the click eventOverlayEntry;

overlayEntry = OverlayEntry(builder: (context) { return Stack(children: <Widget>[ Positioned(top: (height-200) * 0.5-50, left: (width-200) * 0.5-50, Child: GestureDetector(onTap: () { overlayEntry.remove(); Overlay.of(this.context).insert(overlayEntry2); }, child: _itemContainer (Colors. Red. WithOpacity (0.6))))); }); overlayEntry2 = OverlayEntry(builder: (context) { return Stack(children: <Widget>[ Positioned(top: (height-200) * 0.5, left: (width-200) * 0.5, child: GestureDetector(onTap: () { overlayEntry2.remove(); Overlay.of(this.context).insert(overlayEntry3); }, child: _itemContainer (Colors. Orange. WithOpacity (0.6))))); }); overlayEntry3 = OverlayEntry(builder: (context) { return Stack(children: <Widget>[ Positioned(top: (height-200) * 0.5 + 50, left: (width -200) * 0.5 + 50, child: GestureDetector(onTap: () => overlayentry3.remove (), child: _itemContainer(color.blue. WithOpacity (0.6)))))); }); Overlay.of(context).insert(overlayEntry);Copy the code

Matters needing attention

1. Overlay is global Overlay, not current Page, need to redefine the back button, etc. If there is no remove, the float element is still displayed on the previous page. Remove other elements that have not been added to the float layer returns a failure;
return WillPopScope(
    onWillPop: () async {
      if (overListIndex == 6) {
        for (int i = overlayEntryList.length; i > 0; i--) {
          overlayEntryList[i - 1].remove();
        }
        overlayEntryList.clear();
        overIndex = 0;
      } else if (overListIndex == 7) {
        overlayEntry.remove();
      } else if (overListIndex == 8) {
        overlayEntry2.remove();
      } else if (overListIndex == 9) {
        overlayEntry3.remove();
      }
      if (overIndex == 4) {
        overlayEntry.remove();
        overlayEntry0.remove();
      } else if (overIndex == 3) {
        overlayEntry2.remove();
        overlayEntry0.remove();
      } else if (overIndex == 2) {
        overlayEntry3.remove();
        overlayEntry0.remove();
      } else if (overIndex == 5) {
        overlayEntry.remove();
      }
      overIndex = 0;
      return true;
    },
    child: Container(...)
);
Copy the code

2. When using insertAll to add float layer elements, do not add the same OverlayEntry multiple times.
overlayEntry = OverlayEntry(builder: (context) { return Stack(children: <Widget>[ Positioned(top: (height-200) * 0.5-50, left: (width-200) * 0.5-50, Child: GestureDetector(onTap: () => overlayEntry. Remove (), child: _itemContainer(color.red. WithOpacity (0.6)))))); }); OverlayEntry overlayentryList. add(OverlayEntry); overlayEntryList.add(overlayEntry); overlayEntryList.add(overlayEntry); Overlay.of(this.context).insertAll(overlayEntryList);Copy the code

Opaque = true: Opaque = true: Opaque = true: Opaque = true: Opaque = true: Opaque = true: Opaque = true MaintainState: When opaque = true is used, maintainState of the overwritten element is built in advance.
overlayEntryList.add(OverlayEntry(builder: (context) { return Stack(children: <Widget>[ Positioned( top: (height-200) * 0.5-50, left: (width-200) * 0.5-50, Child: GestureDetector(onTap: () {--overIndex; overlayEntryList[overIndex].remove();}, child: _itemContainer(color.red. WithOpacity (0.6)))))); })); overlayEntryList.add(OverlayEntry( opaque: true, maintainState: true, builder: (context) { return Material( color: Animation (0.4), child: Stack(children: <Widget>[toy (top: (height-200) * 0.5, left: (width-200) * 0.5, child: GestureDetector(onTap: () {--overIndex; overlayEntryList[overIndex]. Remove ();}, child: _itemContainer (Colors. Orange. WithOpacity (0.6)))))); })); overlayEntryList.add(OverlayEntry( opaque: true, maintainState: false, builder: (context) { return Material( color: Colors. LightBlueAccent. WithOpacity (0.4), the child: Stack (children: < widgets > [Positioned (top: (height-200) * 0.5 + 50, left: (width -200) * 0.5 + 50, child: GestureDetector(onTap: () {--overIndex; overlayEntryList[overIndex].remove();}, child: _itemContainer(color.blue. WithOpacity (0.6)))))); })); overIndex = overlayEntryList.length; Overlay.of(context).insertAll(overlayEntryList);Copy the code


Overlay case source code


The attempt of Overlay is still basic, and the use scenario is also small. If there are any mistakes, please give more guidance!

Little Monk Aze