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

#はじめに
https://api.flutter.dev/flutter/material/SnackBar-class.html

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

```dart
 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`というファイルを作成します。

```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:

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

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

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

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

ではどうするか？

#staticを使って実装

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

```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 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:

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


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

// 省略

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

#参考
https://stackoverflow.com/questions/60319051/how-to-create-and-use-snackbar-for-reuseglobally-in-flutter