Chapter 04

ボタンを「コンポーネント化」しよう

へぶん
へぶん
2020.12.27に更新

このチャプターでは「ボタン」をコンポーネント化していきましょう。Flutter でコンポーネント化を行う時は、StatelessWidget, StatefulWidget を継承した自作クラスを用意します。

1. 空の StatelessWidget 継承クラスを用意する

Android Studio, VSCode をお使いの方であれば、stless と打ち込めばテンプレートから作ることができます。

空の自作クラスには CustomButton と名付けます。以下のようになります。

class CustomButton extends StatelessWidget {
  const CustomButton({Key key}) : super(key: key);

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

2. 元々の実装をコピペする

空のボタンクラスに、前のチャプターで自作したボタンの実装をコピペしましょう。
以下のようになります。

class CustomButton extends StatelessWidget {
  const CustomButton({Key key}) : super(key: key);

  
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () {
        _incrementCounter();
      },
      child: Container(
        height: 56,
        width: 56,
        decoration: BoxDecoration(
          color: Colors.blue,
          borderRadius: BorderRadius.circular(28),
        ),
        alignment: Alignment.center,
        child: Icon(
          Icons.add,
          color: Colors.white,
        ),
      ),
    );
  }
}

今は以下のようにエラーが出ている状態です。

コンポーネント化したことで、_incrementCounter メソッドの定義が呼び出せなくなってしまったので、ボタンの外側から渡せるようにする必要があります。

3. onTap コールバックを外から渡せるようにする

_incrementCounter を自作ボタンに渡すには、自作ボタンのクラスのコンストラクタでコールバックを渡せるようにするのがいいです。
CustomButton クラスに VoidCallback という型の onTap というフィールドを用意して、コンストラクタに定義を追加しましょう。

class CustomButton extends StatelessWidget {
  const CustomButton({
    this.onTap,
    Key key,
  }) : super(key: key);

  final VoidCallback onTap;
  ...(中略)
}

そして、GestureDetector の onTap でエラーが出ている箇所を用意したコールバックで置き換えます。


Widget build(BuildContext context) {
	return GestureDetector(
		onTap: onTap, <= onTap フィールドを指定する
		child: Container(
		...(中略)
	);
}

4.自作ボタンに _incrementCounter の処理を渡す

最後に 前のチャプターで実装したボタンの箇所を、以下のように自作 Widget で置き換えます。

Scaffold(
 ...(中略)
  floatingActionButton: CustomButton(
    onTap: () {
      _incrementCounter();
    },
  ),
);

動作を確認してみましょう。以下のようにカウンターとして動作するはずです。

結果は前のチャプターと同じですが、一つ進みました。

次のチャプターでは、ボタンにインタラクションを追加するための「状態」を追加していきます。