flutter Toast message prompt box

Inscription
- Holding the sword in the world, starting from your accumulation, wherever you go, you must strive for perfection, that is, toss every day.


This article will describe:
1. In the cross-platform development of flutter
, using Dart to realize the effect of the Toast message prompt box 2. Analysis of the use of Overlay and OverlayEntry


insert image description here

1 How to use Toast

          //default is displayed in the middle
          Toast.toast(context,msg: "displayed in the middle");
          
          Toast.toast(context,msg: "displayed in the middle",position: ToastPostion.center);
          
          Toast.toast(context,msg: "Toast displayed at the top $_count",position: ToastPostion.top);
          
          Toast.toast(context,msg: "Toast $_count displayed at the bottom",position: ToastPostion.bottom);

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

2 Toast source code

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

//Toast display position control
enum ToastPostion {
  top,
  center,
  bottom,
}

class Toast {
  // toast is added to the screen by it
  static OverlayEntry _overlayEntry;
  // Whether the toast is showing
  static bool _showing = false;
  // Open the current time of a new toast to compare whether enough time has been displayed
  static DateTime _startedTime;
  // prompt content
  static String _msg;
  // toast display time
  static int _showTime;
  // background color
  static Color _bgColor;
  // text color
  static Color _textColor;
  // font size
  static double _textSize;
  // show the position
  static ToastPostion _toastPosition;
  // left and right margins
  static double _pdHorizontal;
  // top and bottom margins
  static double _pdVertical;
  static void toast(
    BuildContext context, {
    // displayed text
    String msg,
    //display time in milliseconds
    int showTime = 1000,
    //display background
    Color bgColor = Colors.black,
    //display text color
    Color textColor = Colors.white,
    //display text size
    double textSize = 14.0,
    // display position
    ToastPostion position = ToastPostion.center,
    // padding in the horizontal direction of the text
    double pdHorizontal = 20.0,
    // vertical padding of text
    double pdVertical = 10.0,
  }) async {
    assert(msg != null);
    _msg = msg;
    _startedTime = DateTime.now();
    _showTime = showTime;
    _bgColor = bgColor;
    _textColor = textColor;
    _textSize = textSize;
    _toastPosition = position;
    _pdHorizontal = pdHorizontal;
    _pdVertical = pdVertical;
    //Get OverlayState
    OverlayState overlayState = Overlay.of(context);
    _showing = true;
    if (_overlayEntry == null) {
      //OverlayEntry is responsible for building the layout
      //Insert the constructed layout into the top layer of the entire layout through OverlayEntry
      _overlayEntry = OverlayEntry(
          builder: (BuildContext context) => Positioned(
                //top value, you can change this value to change the position of the toast on the screen
                top: buildToastPosition(context),
                child: Container(
                    alignment: Alignment.center,
                    width: MediaQuery.of(context).size.width,
                    child: Padding(
                      padding: EdgeInsets.symmetric(horizontal: 40.0),
                      child: AnimatedOpacity(
                        opacity: _showing ? 1.0 : 0.0, //target transparency
                        duration: _showing
                            ? Duration(milliseconds: 100)
                            : Duration(milliseconds: 400),
                        child: _buildToastWidget(),
                      ),
                    )),
              ));
      //Insert to the top layer of the entire layout
      overlayState.insert(_overlayEntry);
    } else {
      //Redraw UI, similar to setState
      _overlayEntry.markNeedsBuild();
    }
    // waiting time
    await Future.delayed(Duration(milliseconds: _showTime));
    //Disappear after 2 seconds
    if (DateTime.now().difference(_startedTime).inMilliseconds >= _showTime) {
      _showing = false;
      _overlayEntry.markNeedsBuild();
      await Future.delayed(Duration(milliseconds: 400));
      _overlayEntry.remove();
      _overlayEntry = null;
    }
  }

  //toast draw
  static _buildToastWidget() {
    return Center(
      child: Card(
        color: _bgColor,
        child: Padding(
          padding: EdgeInsets.symmetric(
              horizontal: _pdHorizontal, vertical: _pdVertical),
          child: Text(
            _msg,
            style: TextStyle(
              fontSize: _textSize,
              color: _textColor,
            ),
          ),
        ),
      ),
    );
  }

// set toast position
  static buildToastPosition(context) {
    var backResult;
    if (_toastPosition == ToastPostion.top) {
      backResult = MediaQuery.of(context).size.height * 1 / 4;
    } else if (_toastPosition == ToastPostion.center) {
      backResult = MediaQuery.of(context).size.height * 2 / 5;
    } else {
      backResult = MediaQuery.of(context).size.height * 3 / 4;
    }
    return backResult;
  }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138

3 Overlay与OverlayEntry

3.1 Introduction Analysis

In the Toast source, we used OverlayEntry, so before talking about OverlayEntry, we need to talk about Overlay together.

The resolution of Overlay in English is [overlaid on...], then in flutter, it is a Stack widget, then the overlay entry can be inserted into the overlay through Overlay, so that the independent child window can be suspended on top of other widgets .

Because the Overlay itself uses the Stack layout, the overlay entry can use Positioned or AnimatedPositioned to position itself in the overlay, so in the above Toast source code, we use the layout of the OverlayEntry built by Positioned, and use Positioned to control the sub-layout Alignment, that is, the display position of the Toast we mentioned, such as centering.

When we create MaterialApp, it will automatically create a Navigator, and then create an Overlay; then use this Navigator to manage the interface in the route. It can be understood as similar to the WindowManager in Android, you can use the addView and removeView methods to add or delete Views to the interface.

Then in actual development, if we want to suspend a widget to the surface of the page, we can use Overlay to achieve it, such as our Toast prompt box.

3.2 How to use Overlay and OverlayEntry

Generally, it is to insert child Widgets and mobile Widgets, such as our Toast above, display is to insert Widgets into the existing Widget tree, and hide is to remove


//Create OverlayEntry 
Overlay entry = new  OverlayEntry ( builder : ( ) { 
/*Create the corresponding widget here and return it, commonly used Positioned layout*/

} ) ; 
//Insert OverlayEntry into Overlay 
Overlay .of ( context ) .insert ( overlayEntry ) ; //Call the entry's own remove() method to remove its own entry 
from the overlay .remove ( ) ;

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

4 Analysis of MediaQuery

In flutter development, use MediaQuery to get information such as screen height and width.

MediaQuery.devicePixelRatio The number of physical pixels corresponding to each logical pixel
MediaQuery.size.width The screen width
expressed in logical pixels MediaQuery.size.height The screen height expressed in logical pixels MediaQuery.padding.top The
upper part of the screen is blocked by the system UI The logical height of the part (ie: status bar height)
MediaQuery.textScaleFactor When displaying text, each logical pixel corresponds to the font pixel

4.1 Brief Analysis of Pixels

The height, width and font size of controls in Flutter use logical pixels, not actual physical pixels. There is a detailed analysis in the article
" Android Screen Adaptation Series Review Column "

Actual pixels = logical pixels * MediaQuery.devicePixelRatio
  • 1

[1] At present, the Flutter series of tutorials are published for free on the watermelon video, which is updated daily. Welcome to pay attention to receive reminders and click to view the tips

insert image description here


[2] This official account will publish a series of special articles for the first time, and paid video courses will be published in the official account for free. On your way to work or just before going to bed, this official account is a small choice for you to browse knowledge and dry goods. , Collection is not as good as action, at that moment, the official account will remind you that it is time to learn.
insert image description here

Related: flutter Toast message prompt box