【從零開始學 Flutter 程式設計】SnackBar 提示元件

【從零開始學 Flutter 程式設計】線上教學課程目錄 使用 Dart 程式語言,開發 Android 和 iOS APP 應用程式。

SnackBar 提示元件

SnackBar 提示元件,會在螢幕下方,彈跳顯示訊息,幾秒後消失。

範例:顯示 SnackBar 簡單基本訊息

final snackBar = new SnackBar(content: new Text('顯示訊息'));
Scaffold.of(context).showSnackBar(snackBar);

執行畫面

完整程式碼

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        home: Scaffold(
      appBar: AppBar(
        title: Text('HKT線上教室'),
      ),
      body: HomePage(),
    ));
  }
}

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: RaisedButton(
        child: Text('顯示 SnackBar 訊息'),
        onPressed: () {
        //顯示 SnackBar 簡單基本訊息
          final snackBar = new SnackBar(content: new Text('顯示訊息'));
          Scaffold.of(context).showSnackBar(snackBar);
        },
      ),
    );
  }
}

範例:錯誤示範完整程式碼

注意事項:
SnackBar 要顯示訊息是透過 Scaffold的showSnackBar 方法來顯示。所以要顯示訊息,務必要先拿到 Scaffold 的 context,否則會報錯無法顯示。當然可以直接在 body 後包一層 Builder 快速解決,不過 KT 建議不要寫出波動拳程式結構。所以在最一開始起手式章節 KT 就直接建議拆開,分成一小塊一小塊邏輯程式,維護、閱讀比較方便,降低程式耦合性比較容易擴充與變動。
/*
 * 錯誤程式,執行會發生錯誤
 */
 
import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        home: Scaffold(
      appBar: AppBar(
        title: Text('HKT線上教室'),
      ),
      body: Center(
        child: RaisedButton(
          child: Text('顯示 SnackBar 訊息'),
          onPressed: () {
            final snackBar = new SnackBar(content: new Text('顯示訊息'));
            Scaffold.of(context).showSnackBar(snackBar);
          },
        ),
      ),
    ));
  }
}

執行後會出現錯誤

會出現類似下方,錯誤 Log 訊息
flutter: ══╡ EXCEPTION CAUGHT BY GESTURE ╞═══════════════════════════════════════════════════════════════════
flutter: The following assertion was thrown while handling a gesture:
flutter: Scaffold.of() called with a context that does not contain a Scaffold.
flutter: No Scaffold ancestor could be found starting from the context that was passed to Scaffold.of(). This
flutter: usually happens when the context provided is from the same StatefulWidget as that whose build
flutter: function actually creates the Scaffold widget being sought.
flutter: There are several ways to avoid this problem. The simplest is to use a Builder to get a context that
flutter: is "under" the Scaffold. For an example of this, please see the documentation for Scaffold.of():
flutter:   https://api.flutter.dev/flutter/material/Scaffold/of.html
flutter: A more efficient solution is to split your build function into several widgets. This introduces a
flutter: new context from which you can obtain the Scaffold. In this solution, you would have an outer widget
flutter: that creates the Scaffold populated by instances of your new inner widgets, and then in these inner
flutter: widgets you would use Scaffold.of().
flutter: A less elegant but more expedient solution is assign a GlobalKey to the Scaffold, then use the
flutter: key.currentState property to obtain the ScaffoldState rather than using the Scaffold.of() function.
flutter: The context used was:
flutter:   MyApp
flutter:
flutter: When the exception was thrown, this was the stack:
flutter: #0      Scaffold.of (package:flutter/src/material/scaffold.dart:1188:5)
flutter: #1      MyApp.build. (package:demo_flutter/main.dart:20:22)
flutter: #2      _InkResponseState._handleTap (package:flutter/src/material/ink_well.dart:635:14)
flutter: #3      _InkResponseState.build. (package:flutter/src/material/ink_well.dart:711:32)
flutter: #4      GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:182:24)
flutter: #5      TapGestureRecognizer._checkUp (package:flutter/src/gestures/tap.dart:365:11)
flutter: #6      TapGestureRecognizer.handlePrimaryPointer (package:flutter/src/gestures/tap.dart:275:7)
flutter: #7      PrimaryPointerGestureRecognizer.handleEvent (package:flutter/src/gestures/recognizer.dart:455:9)
flutter: #8      PointerRouter._dispatch (package:flutter/src/gestures/pointer_router.dart:75:13)
flutter: #9      PointerRouter.route (package:flutter/src/gestures/pointer_router.dart:102:11)
flutter: #10     _WidgetsFlutterBinding&BindingBase&GestureBinding.handleEvent (package:flutter/src/gestures/binding.dart:218:19)
flutter: #11     _WidgetsFlutterBinding&BindingBase&GestureBinding.dispatchEvent (package:flutter/src/gestures/binding.dart:198:22)
flutter: #12     _WidgetsFlutterBinding&BindingBase&GestureBinding._handlePointerEvent (package:flutter/src/gestures/binding.dart:156:7)
flutter: #13     _WidgetsFlutterBinding&BindingBase&GestureBinding._flushPointerEventQueue (package:flutter/src/gestures/binding.dart:102:7)
flutter: #14     _WidgetsFlutterBinding&BindingBase&GestureBinding._handlePointerDataPacket (package:flutter/src/gestures/binding.dart:86:7)
flutter: #18     _invoke1 (dart:ui/hooks.dart:250:10)
flutter: #19     _dispatchPointerDataPacket (dart:ui/hooks.dart:159:5)
flutter: (elided 3 frames from package dart:async)
flutter:
flutter: Handler: "onTap"
flutter: Recognizer:
flutter:   TapGestureRecognizer#90ba4
flutter: ════════════════════════════════════════════════════════════════════════════════════════════════════

範例:顯示 SnackBar 訊息與自定義按鈕

void showMySnackBar(BuildContext context) {
    final snackBar = new SnackBar(
      content: new Text('顯示訊息'),
      action: SnackBarAction(
        label: '復原',
        onPressed: () {
          print('復原...');
        },
      ),
    );
    Scaffold.of(context).showSnackBar(snackBar);
  }

執行畫面

完整程式碼

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        home: Scaffold(
      appBar: AppBar(
        title: Text('HKT線上教室'),
      ),
      body: HomePage(),
    ));
  }
}

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: RaisedButton(
        child: Text('顯示 SnackBar 訊息'),
        onPressed: () {
          showMySnackBar(context);
        },
      ),
    );
  }

  //顯示 SnackBar 訊息與自定義按鈕
  void showMySnackBar(BuildContext context) {
    final snackBar = new SnackBar(
      content: new Text('顯示訊息'),
      action: SnackBarAction(
        label: '復原',
        onPressed: () {
          print('復原...');
        },
      ),
    );
    Scaffold.of(context).showSnackBar(snackBar);
  }
}

那這次的課程就介紹到這邊囉~
順帶一提,KT 線上教室,臉書粉絲團,會不定期發佈相關資訊,不想錯過最新資訊,不要忘記來按讚,加追蹤喔!也歡迎大家將這套課程分享給更多人喔。
我們下次再見囉!!!掰掰~

這個網誌中的熱門文章

16天記下7000單字

2023 最新入門零基礎 Kotlin教學【從零開始學 Kotlin 程式設計】Kotlin 教學課程目錄 (Android Kotlin, IntelliJ IDEA, Android Studio, Android APP 開發教學)

2022 最新入門零基礎 Flutter教學 【Flutter 程式設計入門實戰 30 天】Flutter 教學課程目錄 (IntelliJ IDEA 開發教學)

nano 文字編輯器

【從零開始學 Flutter 程式設計】SharedPreferences 設定檔資料存取