3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Flutter SnackBarを共通化して、用途に応じて再利用する方法

Last updated at Posted at 2021-05-29

はじめに

SnackBarのデザインをカスタマイズした場合、こんな感じでやたらとコードが長くなってしまいますよね。。

 ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(
            action: SnackBarAction(
              label: 'Action',
              onPressed: () {
                // Code to execute.
              },
            ),
            content: const Text('Awesome SnackBar!'),
            duration: const Duration(milliseconds: 1500),
            width: 280.0, // Width of the SnackBar.
            padding: const EdgeInsets.symmetric(
              horizontal: 8.0, // Inner padding for SnackBar content.
            ),
            behavior: SnackBarBehavior.floating,
            shape: RoundedRectangleBorder(
              borderRadius: BorderRadius.circular(10.0),
            ),
          ),

これをSnackBarを表示させる部分に毎回書くのをなんとか避けられないか?を調べてみました。

SnackBarを再利用するために外部ファイルからimportできるようにします!

SnackBarは普通のWidgetと同じように外部で作成できない

まずmy_snackbar.dartというファイルを作成します。

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

class MySnackBar extends StatelessWidget {
  final String message;
  MySnackBar({@required this.message});

 @override
  Widget build(BuildContext context) {
    return SnackBar(
      content: Row(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          Icon(
            Icons.check,
            color: Colors.white,
          ),
          SizedBox(
            width: 10,
          ),
          Text(message),
        ],
      ),
      duration: const Duration(milliseconds: 3000),
      padding: const EdgeInsets.symmetric(
        horizontal: 8.0, // Inner padding for SnackBar content.
      ),
      behavior: SnackBarBehavior.floating,
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.circular(15),
      ),
    );
  }
}

他のWidget(CardとかRowとか)ならこんなやり方でうまくいくのですが、SnackBarはダメです:frowning:

ScaffoldMessenger.of(ctx).showSnackBar(MySnackBar(message: 'Save',));

こうやって使おうとすると

The argument type 'MySnackBar' can't be assigned to the parameter type 'SnackBar'.

こんなエラーが出ます。。。
Flutterではよくある「型が違うよ!」エラーです

ではどうするか?

staticを使って実装

ScaffoldMessengerの段階から呼び出す方法がありました!
それがstaticを使う方法です。

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

class MySnackBar extends StatelessWidget {
  final String message;
  MySnackBar({@required this.message});

  @override
  Widget build(BuildContext context) {
    return Container();
  }

  // 成功の場合のSnackBar
  static show(
    BuildContext context,
    String message,
  ) {
    ScaffoldMessenger.of(context).showSnackBar(SnackBar(
      content: Row(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          Icon(
            Icons.check,
            color: Colors.white,
          ),
          SizedBox(
            width: 10,
          ),
          Text(message),
        ],
      ),
      duration: const Duration(milliseconds: 3000),
      padding: const EdgeInsets.symmetric(
        horizontal: 8.0, // Inner padding for SnackBar content.
      ),
      behavior: SnackBarBehavior.floating,
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.circular(15),
      ),
    ));
  }

 // 失敗の場合のSnackBar
  static showError(
    BuildContext context,
    String message,
  ) {
    ScaffoldMessenger.of(context).showSnackBar(SnackBar(
      content: Row(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          Icon(
            Icons.error,
            color: Colors.white,
          ),
          SizedBox(
            width: 10,
          ),
          Text(message),
        ],
      ),
      duration: const Duration(milliseconds: 3000),
      padding: const EdgeInsets.symmetric(
        horizontal: 8.0, // Inner padding for SnackBar content.
      ),
      behavior: SnackBarBehavior.floating,
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.circular(15),
      ),
    ));
  }
}

こんな感じで用途に応じてSnackBarを再利用できました:middle_finger:

👆の例では
・成功の場合はチェックマークのアイコン
・失敗の場合はエラーのアイコン
というように違いがあります。

// my_snackbar.dartをimport
import '../widgets/common_UI/my_snackbar.dart'; 

// 省略

 .then(
     // 成功の場合のSnackBar
     (value) => MySnackBar.show(ctx, '追加しました!'),
      )
      .catchError((error) {
      //  // 失敗の場合のSnackBar
        MySnackBar.showError(ctx, 'エラー発生!追加に失敗。。。');
       });

参考

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?