編寫了一個輔助Flutter彈出Toast的Package

boyan01發表於2019-02-18

前言

在日常 APP 開發過程中,經常會使用到 Toast 來彈出應用內的小通知來告知使用者一些小情況。但 Flutter 中並沒有帶有類似 Toast 這樣的工具類,翻了 StackOverflow 都是建議使用 SnackBar 來彈出提示。例如:

  Scaffold.of(context).showSnackBar(SnackBar(content: Text('message')));
複製程式碼

個人不太滿意這樣的實現方式。在巧合之下,我發現了 Overlay 這個類,於是誕生了借用 Overlay 來實現 toast 的想法。

專案的地址在 github.com/boyan01/ove…

預覽

先放兩張效果圖來展示最終效果

notification toast
notification
toast

怎麼使用

使用的方式很簡單,引入包後簡單呼叫即可。

//彈出toast
toast(context, '訊息');

//彈出notification
showSimpleNotification(context, Text('訊息'));
複製程式碼

實現過程

整體實現的核心邏輯在 showOverlay(BuildContext, builder, ...)中:

NotificationEntry showOverlay(
    BuildContext context, AnimatedOverlayWidgetBuilder builder,
    {bool autoDismiss = true, Curve curve}) {
  assert(autoDismiss != null);

  GlobalKey<AnimatedOverlayState> key = GlobalKey();

  //步驟1 建立OverlayEntry
  final entry = OverlayEntry(builder: (context) {
    return AnimatedOverlay(
      key: key,
      builder: builder,
      curve: curve,
    );
  });

  NotificationEntry notification = NotificationEntry(entry, key);

  //步驟2 將OverlayEntry新增到Overlay中
  Overlay.of(context).insert(entry);

  if (autoDismiss) {
    Future.delayed(kNotificationDuration + kNotificationSlideDuration)
        .whenComplete(() {
      //ensure entry has been inserted into screen
      WidgetsBinding.instance
          .scheduleFrameCallback((_) => notification.dismiss());
    });
  }
  return notification;
}
複製程式碼

主要分為這麼幾個部分:

  1. 建立OverlayEntry。為了方便實現動畫效果,我抽出了一個單獨的 widget —— AnimatedOverlay
  2. OverlayEntry 新增到 Overlay 中。
  3. 如果 autoDismiss 設定為 true 的話,就在一段事件之後(kNotificationDuration + kNotificationSlideDuration),將 OverlayEntryOverlay 中移除。

弊端

使用 Overlay 來實現 Toast 效果很簡便,但是有一個弊端:無法在後臺彈出

最後

如果大家有什麼想法或者建議的話,可以直接在 Github 中提 issues 或者 PR,這樣可以讓庫的可用性更高一些,謝謝大家。

相關文章