
В этом руководстве мы собираемся создать собственную утилиту тостов без использования сторонних библиотек. Я поделюсь с вами сутью. Gist можно изменить в соответствии с вашими требованиями.
Требования:
- Утилита для отображения / скрытия и размещения тоста.
- Декоратор, который может помочь обновить пользовательские границы и углы.
- Виджет, отображаемый как тост.
Служебный метод отображения / скрытия тоста:
Этот метод потребует позиции, контекста и продолжительности виджета, а также самого виджета. Нам также понадобится одноэлементный класс. Этот класс захватит виджет. Чтобы мы могли удалить виджет в Будущем.
//Position
enum ToastGravity {
bottom,
center,
top
}
//public method:
class ToastUtil {
static void show(Widget widget, BuildContext context,
{int duration = 2,
ToastGravity gravity = ToastGravity.bottom,
}) {
// hide older tost
//show new toast
}
}
//singleton view - private
class _ToastView {
static final _ToastView _singleton = new _ToastView._internal();
factory _ToastView() {
return _singleton;
}
_ToastView._internal();
}
Мы собираемся показать виджет на оверлее как объект наложения. Наш _ToastView должен содержать состояние наложения и overlayEntry. Нам также понадобится один флаг, чтобы проверить, был ли удален старый оверлей или нет.
class _ToastView {
static OverlayState overlayState;
static OverlayEntry _overlayEntry;
static bool _isVisible = false;
}
Показать / скрыть виджет для наложения:
static void createViewToast(
BuildContext context,
int duration,
ToastGravity gravity,
Widget widget,
) async {
overlayState = Overlay.of(context);
_overlayEntry = OverlayEntry(
//_ToastWidget => we shall be implementing this widget later
builder: (BuildContext context) => _ToastWidget(
widget: widget,
gravity: gravity,
)
);
_isVisible = true;
overlayState.insert(_overlayEntry);
//wait for given duration before closing.
await new Future.delayed(Duration(
seconds: duration));
dismiss();
}
В приведенном выше коде мы видим частный виджет-оболочку _ToastWidget. этот виджет предназначен для позиционирования виджета в зависимости от силы тяжести.
class _ToastWidget extends StatelessWidget {
_ToastWidget({
Key key,
@required this.widget,
@required this.gravity,
}) : super(key: key);
final Widget widget;
final ToastGravity gravity;
@override
Widget build(BuildContext context) {
return new Positioned(
top: gravity == ToastGravity.top ? MediaQuery.of(context).viewInsets.top + 50 : null,
bottom:
gravity == ToastGravity.bottom ? MediaQuery.of(context).viewInsets.bottom + 50 : null,
child: Material(
color: Colors.transparent, //use the widget color
child: widget,
));
}
}
Декоратор, который помогает обновлять пользовательские границы и углы:
Декоратор принимает виджет с декоративными параметрами, такими как заполнение полей и т. Д. Вы можете передать свой виджет непосредственно в ToastUtil или обернуть его в ToastDecorator, чтобы избежать повторяющегося кода оформления.
class ToastDecorator extends StatelessWidget {
final Widget widget;
final Color backgroundColor;
final Border border;
final EdgeInsets margin;
final EdgeInsets padding;
final BorderRadius borderRadius;
ToastDecorator({
@required this.widget,
this.backgroundColor = Colors.black,
this.border = const Border(),
this.margin = const EdgeInsets.symmetric(horizontal: 20),
this.padding = const EdgeInsets.fromLTRB(16, 10, 16, 10),
this.borderRadius = const BorderRadius.all(Radius.circular(20.0))
}) {}
@override
Widget build(BuildContext context) {
return Container(
width: MediaQuery.of(context).size.width,
child: Container(
alignment: Alignment.center,
width: MediaQuery.of(context).size.width,
child: Container(
decoration: BoxDecoration(
color: backgroundColor,
borderRadius: this.borderRadius,
border: this.border,
),
margin: margin,
padding: padding,
child: widget,
)
)
);
}
}
Показан тост:
//Show warning Toast on top of view
ToastUtil.show(
ToastDecorator(
widget: Text(
"warning message",
style: TextStyle(color: Colors.white)
),
backgroundColor: Colors.red,
),
context,
gravity: ToastGravity.top);
},
//Show information Toast on bottom of view
ToastUtil.show(
ToastDecorator(
widget: Text(
"info message",
style: TextStyle(color: Colors.white)
),
backgroundColor: Colors.black,
),
context,
gravity: ToastGravity.bottom);
//Show Custom view
ToastDecorator(
widget: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
const ListTile(
leading: Icon(Icons.album, size: 50),
title: Text('Heart Shaker', style: TextStyle(color: Colors.white)),
subtitle: Text('TWICE', style: TextStyle(color: Colors.white)),
),
],
),
backgroundColor: Colors.greenAccent,
),
context,
gravity: ToastGravity.top);
Полный код: