Kodokon kodokon.com

対話性:ボタン、StatefulWidget、setState

ボタンのタップに反応し、setStateで表示を更新して、画面に命を吹き込みましょう。

10 分 · 3 問

このレッスンを Kodokon で開く

私たちの画面はきれいですが、固まっています。ユーザーの操作に反応するときが来ました。標準的なMaterial 3のボタンはElevatedButtonです。二つの欠かせないパラメーターを取ります。childは表示される中身(多くはText)で、onPressedはタップしたときに実行する関数です。このようにパラメーターとして渡される関数はコールバックと呼ばれます。あなた自身がそれを呼ぶのではなく、Flutterが適切なタイミングで代わりに呼んでくれます。() { ... }という構文は、名前のない無名関数を、その場に直接書いて作ります。

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

Widget buildHelloButton() {
  return ElevatedButton(
    onPressed: () {
      debugPrint("Button pressed!");
    },
    child: const Text("Tap here"),
  );
}
タップするたびにコンソールに書き込むボタン

debugPrintはコンソールに書き込みます……が、画面そのものは変わりません。なぜでしょう? それは、StatelessWidget状態を持たないウィジェット)が固まっているからです。一度作られると、もう変われません。変化する値を表示するには、StatefulWidget状態を持つウィジェット)が必要です。状態とは、ウィジェットの一生の間に変わりうるデータの集まりです。カウンター、チェックされた箱、入力されたテキストなど……。StatefulWidgetは常にStateクラスと一対で、このクラスがそのデータを保持し、buildメソッドを含みます。これが初期からの大定番、カウンターです。

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

void main() {
  runApp(const CounterApp());
}

class CounterApp extends StatelessWidget {
  const CounterApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(useMaterial3: true),
      home: const CounterPage(),
    );
  }
}

class CounterPage extends StatefulWidget {
  const CounterPage({super.key});

  @override
  State<CounterPage> createState() =>
      _CounterPageState();
}

class _CounterPageState extends State<CounterPage> {
  int count = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text(
              "Counter: $count",
              style: const TextStyle(fontSize: 32),
            ),
            const SizedBox(height: 16),
            ElevatedButton(
              onPressed: () {
                setState(() {
                  count = count + 1;
                });
              },
              child: const Text("+1"),
            ),
          ],
        ),
      ),
    );
  }
}
カウンター:完全なStatefulWidget

しくみは三つのステップで成り立ちます。1) count変数は_CounterPageStateの中にあります。それが状態です。2) タップするたびに、コールバックがsetStateを呼びます。このメソッドは状態を変更し、そして何かが変わったことをFlutterに伝えます3) するとFlutterはbuildをもう一度実行し、countの新しい値で画面を描き直します。この考え方を覚えておきましょう。画面を直接変えることは決してなく、データを変えて、表示はFlutterに任せるのです。

理解度チェック

このレッスンの要点をしっかり覚えているか確認しましょう。

  1. ElevatedButtonのonPressedパラメーターは何のためのものですか?
    • ボタンに表示するテキストを設定するため
    • ボタンがタップされたときに実行する関数を提供するため
    • ボタンの色を選ぶため
  2. StatelessWidgetではなくStatefulWidgetを使うべきなのはどんなときですか?
    • 表示が、時間とともに変わるデータに依存するとき
    • ウィジェットが三つより多くの子を含むとき
    • アプリをより速く起動させたいとき
  3. setStateを呼ばずにcountを変えるとどうなりますか?
    • アプリがすぐにクラッシュする
    • 変数はメモリの中で変わるが、画面は更新されない
    • Flutterが代わりに自動でsetStateを呼ぶ