Toast является наиболее часто используемым компонентом подсказок на Android. Его преимуществами являются статический вызов и глобальное отображение. Его можно вызывать где угодно, не затрагивая макет интерфейса вообще. Простота вызова сравнима с Logger. .
Однако Flutter не предоставляет нам интерфейса Toast.Есть два способа добиться эффекта Toast: один — подключиться к нативному проекту Android/iOS, а второй — добиться этого без использования Flutter.
В этой статье используется второе решение для его реализации.С одной стороны, доступ к нативному коду требует большой рабочей нагрузки и порога для двусторонней разработки, и это не способствует будущему расширению стиля.С другой стороны, тост реализован чистый Flutter действительно очень эффективен, а пользовательский стиль также очень удобен. По сравнению с RN, движок рендеринга Flutter очень мощный. В основном, эффекты, которые могут быть достигнуты с помощью Flutter, не рекомендуется делать нативными. Однако RN не имеет собственного движка рендеринга. Из-за ограничений производительности RN требует частого доступа. , поэтому я люблю Flutter.
Основными компонентами, используемыми в этой статье, являютсяOverlay
, этот компонент предоставляет функцию динамической вставки макетов в дерево рендеринга Flutter, так что у нас есть возможность вставлять всплывающие уведомления поверх всех компонентов, включая маршрутизацию.
Создайте проект на флаттере
Блоги Flutter этой серии продуктов начнутся с создания чистого проекта Flutter.После создания проекта поместите кнопку в макет, чтобы облегчить запуск вызовов Toast.
Код: опущен.
Вставить макет тоста с наложением
Поскольку мы хотим реализовать глобальные статические вызовы, сначала создайте класс инструмента и создайте статический метод show в этом классе:
class Toast {
static show(BuildContext context, String msg) {
//这里实现toast的弹出逻辑
}
}
Это очень распространенный статический метод вызова. Вам нужно вызвать Toast.show(context, "ваше сообщение"); в одном из ваших обратных вызовов, чтобы завершить отображение всплывающего уведомления, независимо от проблемы вложенности макета.
Далее мы вставляем тост в макет в методе show:
class Toast {
static show(BuildContext context, String msg) {
var overlayState = Overlay.of(context);
OverlayEntry overlayEntry;
overlayEntry = new OverlayEntry(builder: (context) {
return buildToastLayout(msg);
});
overlayState.insert(overlayEntry);
}
static LayoutBuilder buildToastLayout(String msg) {
return LayoutBuilder(builder: (context, constraints) {
return IgnorePointer(
ignoring: true,
child: Container(
child: Material(
color: Colors.white.withOpacity(0),
child: Container(
child: Container(
child: Text(
"${msg}",
style: TextStyle(color: Colors.white),
),
decoration: BoxDecoration(
color: Colors.black.withOpacity(0.6),
borderRadius: BorderRadius.all(
Radius.circular(5),
),
),
padding: EdgeInsets.symmetric(vertical: 10, horizontal: 10),
),
margin: EdgeInsets.only(
bottom: constraints.biggest.height * 0.15,
left: constraints.biggest.width * 0.2,
right: constraints.biggest.width * 0.2,
),
),
),
alignment: Alignment.bottomCenter,
),
);
});
}
}
В методе show в макет вставляется оверлей.
В это время вы можете увидеть подсказку в стиле Toast в интерфейсе, вызвав метод Toast.show.
Однако этот ToastView не исчезнет, он будет оставаться на интерфейсе все время, что явно не то, что нам нужно.
Заставить Toast автоматически исчезнуть
Мы продолжаем преобразовывать этот Toast, чтобы он мог автоматически исчезать.
Создайте класс с именем ToastView для управления каждым вставленным ToastView:
class ToastView {
OverlayEntry overlayEntry;
OverlayState overlayState;
bool dismissed = false;
_show() async {
overlayState.insert(overlayEntry);
await Future.delayed(Duration(milliseconds: 3500));
this.dismiss();
}
dismiss() async {
if (dismissed) {
return;
}
this.dismissed = true;
overlayEntry?.remove();
}
}
Таким образом инкапсулируется управление отображением и исчезновением ToastView. Затем вызовите его в методе show Toast
class Toast {
static show(BuildContext context, String msg) {
var overlayState = Overlay.of(context);
OverlayEntry overlayEntry;
overlayEntry = new OverlayEntry(builder: (context) {
return buildToastLayout(msg);
});
var toastView = ToastView();
toastView.overlayState = overlayState;
toastView.overlayEntry = overlayEntry;
toastView._show();
}
...
}
Через вышеуказанный метод реализован глобальный статический вызов Тоста, и вставлена глобальная раскладка, и отображается Тост, который автоматически исчезнет через 3,5 секунды, но этот тост кажется странным, да, у него нет анимации, давайте произнести этот тост Добавить анимацию.
Добавить анимацию в тост
Эта анимация Toast является расширенным приложением Flutter. Она включает в себя масштабирование, смещение, настраиваемый дифференциал, AnimatedBuilder и другие функции. Основная часть этой статьи состоит в том, чтобы представить использование Overlay и инкапсуляцию ToastView. Если вы говорите об использовании анимации здесь Слишком много расхождений.Поговорим об анимации отдельно после ограничения места.Здесь объясню исходя из вашего понимания системы анимации.
class Toast {
static show(BuildContext context, String msg) {
var overlayState = Overlay.of(context);
var controllerShowAnim = new AnimationController(
vsync: overlayState,
duration: Duration(milliseconds: 250),
);
var controllerShowOffset = new AnimationController(
vsync: overlayState,
duration: Duration(milliseconds: 350),
);
var controllerHide = new AnimationController(
vsync: overlayState,
duration: Duration(milliseconds: 250),
);
var opacityAnim1 =
new Tween(begin: 0.0, end: 1.0).animate(controllerShowAnim);
var controllerCurvedShowOffset = new CurvedAnimation(
parent: controllerShowOffset, curve: _BounceOutCurve._());
var offsetAnim =
new Tween(begin: 30.0, end: 0.0).animate(controllerCurvedShowOffset);
var opacityAnim2 = new Tween(begin: 1.0, end: 0.0).animate(controllerHide);
OverlayEntry overlayEntry;
overlayEntry = new OverlayEntry(builder: (context) {
return ToastWidget(
opacityAnim1: opacityAnim1,
opacityAnim2: opacityAnim2,
offsetAnim: offsetAnim,
child: buildToastLayout(msg),
);
});
var toastView = ToastView();
toastView.overlayEntry = overlayEntry;
toastView.controllerShowAnim = controllerShowAnim;
toastView.controllerShowOffset = controllerShowOffset;
toastView.controllerHide = controllerHide;
toastView.overlayState = overlayState;
preToast = toastView;
toastView._show();
}
...
}
class ToastView {
OverlayEntry overlayEntry;
AnimationController controllerShowAnim;
AnimationController controllerShowOffset;
AnimationController controllerHide;
OverlayState overlayState;
bool dismissed = false;
_show() async {
overlayState.insert(overlayEntry);
controllerShowAnim.forward();
controllerShowOffset.forward();
await Future.delayed(Duration(milliseconds: 3500));
this.dismiss();
}
dismiss() async {
if (dismissed) {
return;
}
this.dismissed = true;
controllerHide.forward();
await Future.delayed(Duration(milliseconds: 250));
overlayEntry?.remove();
}
}
class ToastWidget extends StatelessWidget {
final Widget child;
final Animation<double> opacityAnim1;
final Animation<double> opacityAnim2;
final Animation<double> offsetAnim;
ToastWidget(
{this.child, this.offsetAnim, this.opacityAnim1, this.opacityAnim2});
@override
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: opacityAnim1,
child: child,
builder: (context, child_to_build) {
return Opacity(
opacity: opacityAnim1.value,
child: AnimatedBuilder(
animation: offsetAnim,
builder: (context, _) {
return Transform.translate(
offset: Offset(0, offsetAnim.value),
child: AnimatedBuilder(
animation: opacityAnim2,
builder: (context, _) {
return Opacity(
opacity: opacityAnim2.value,
child: child_to_build,
);
},
),
);
},
),
);
},
);
}
}
class _BounceOutCurve extends Curve {
const _BounceOutCurve._();
@override
double transform(double t) {
t -= 1.0;
return t * t * ((2 + 1) * t + 2) + 1.0;
}
}
Это очень длинный кусок кода. Я не хотел вставлять на него столько кода, но анимация слишком длинная. Если не вставить код, он будет слишком пустым. Можно только вставить. Давайте поговорим об этом.
Приведенный выше код разделен на четыре части:
В первом абзаце создайте три анимации в методе show, анимацию смещения и постепенного появления отображения Toast и анимацию постепенного исчезновения Toast, а затем передайте контроллеры этих трех анимаций ToastView в управлять воспроизведением анимации.
Раздел 2, получите три контроллера анимации в TOASTVIEW и управляйте воспроизведением анимации в методах Show и Dismiss.
В третьем абзаце создайте собственный виджет и используйте три анимированных компоновщика для создания анимации, а также оберните макет TOAST в методе show.
В четвертом абзаце определяется различие анимации. Flutter предоставляет множество различий анимации, но ни один из них не является тем, что нам нужно, поэтому здесь определяется различие анимации, которое возвращается один раз, чтобы управлять анимацией смещения ToastView Effect.
Пока в этом тосте встречались самые основные стили, глобальные вызовы, всплывающие окна с анимацией и автоматическое затухание и исчезновение после задержки в 3,5 секунды.
Предотвратите непрерывные вызовы, вызывающие накопление всплывающих уведомлений
Но все еще есть проблема, потому что стиль Toast полупрозрачный черный, Если он вызывается несколько раз подряд, несколько Toasts всплывают одновременно и складываются вместе, что выглядит очень черным.
Сделаем еще одну обработку.Перед показом определите, есть ли уже отображаемый Toast.Если есть,то сразу отклоните его.
static ToastView preToast;
static show(BuildContext context, String msg) {
preToast?.dismiss();
preToast = null;
...
preToast = toastView;
toastView._show();
}
...
}
Это оно,?.
Эффекты операторов и Котлин одинаковы, а пустой указатель безопасен, очень удобно.
Больше галантерейных товаров перемещается в мой личный блогwww.nightfarmer.top/