【Flutter】自作Widgetにプロパティを追加する方法

Flutterの自作Widget(カスタムWidget)に独自のプロパティを追加する方法を解説します。

確認環境: Dart 3.3.3, Flutter 3.19.5

ベースの自作Widget

例として内部にボタンのみを実装したシンプルな自作Widgetを考えます。現時点ではStatelessWidgetでも問題ありませんが、後々状態を持たせるためStatefulWidgetで用意しておきます。

StatefulWidgetはFlutterのお決まりとして、以下のように2つのクラスを作成します。

Dart
class MyStatefulWidget extends StatefulWidget {
  @override
  State<MyStatefulWidget> createState() => _MyStatefulWidgetState();
}

class _MyStatefulWidgetState extends State<MyStatefulWidget> {
  @override
  Widget build(BuildContext context) {
    return OutlinedButton(onPressed: null, child: Text('Button'));
  }
}

プロパティを追加する

この自作Widgetにボタンが押された回数を保持しておき、それを受け取れるようなプロパティを追加してみます。実装は以下のようになります。

Dart
class MyStatefulWidget extends StatefulWidget {
  @override
  State<MyStatefulWidget> createState() => _MyStatefulWidgetState();

  // 独自プロパティを定義
  final ValueChanged<int> myProperty;
  // コンストラクタで独自プロパティへアクセスできるようにする
  const MyStatefulWidget({required this.myProperty}); 
}

class _MyStatefulWidgetState extends State<MyStatefulWidget> {
  int _count = 0; // 本Widgetにおける状態(State)

  @override
  Widget build(BuildContext context) {
    return OutlinedButton(
        onPressed: () {
          _count++;
          // MyStatefulWidgetのプロパティにwidget変数経由でアクセスできる
          widget.myProperty(_count);
        },
        child: Text('Button'));
  }
}

MyStatefulWidgetクラスの方は、独自プロパティをクラスに追加し、呼び出し側ではコンストラクタ経由でアクセスすることになるため、コンストラクタの引数として追加したプロパティを指定します。

今回プロパティをValueChanged<int>型で定義していますが、これはFlutterのbasic_types.dartで定義されている型で、引数を1つ持つような関数となっています。

Dart
typedef ValueChanged<T> = void Function(T value);

_MyStatefulWidgetStateクラスには押した回数を保持する_count変数を追加しました。これがStateとなります。

ボタンが押されたタイミング(onPressed)でプロパティに指定された関数を呼ぶようにしたいのですが、_MyStatefulWidgetStateクラスからMyStatefulWidgetクラスにアクセスするにはwidget変数を経由する必要があります。この変数はState<MyStatefulWidget>を継承することで自動的に利用できます。

呼び出し側の実装

呼び出し側では以下のようにしてプロパティに関数をセットします。

Dart
MyStatefulWidget(myProperty: (value) {
  // valueにボタンが押された回数が入り呼び出される
})

コード全文

コードを全体像をGitHubで公開しています。こちらからDartPadで実行を試して頂くことも可能です。

コメント

タイトルとURLをコピーしました