Skip to content

3 実践1 リスト

Kenichiro Watanabe edited this page Jul 25, 2018 · 5 revisions

TODOアプリ実践① リスト

1. 初期コードのおさらい

  • lib/main.dartをシンプルにすると、下記のコードになる
  • これだけで「ボタンを押すたびに数値が変わるネイティブアプリ画面」が全て構成されている
import 'package:flutter/material.dart';

//-------------------------------------
// メイン関数: 全てはここから始まる!
void main() {
  // アプリの起点となるrunApp()関数の引数に、
  // Widgetを渡してあげると、それが画面の起点となって表示される
  runApp(new MyApp());
}

//-------------------------------------
// StatelessWidget: アプリのルート画面
// MyAppは実際には画面を持っておらず、その中身に描画させている
class MyApp extends StatelessWidget {
  // Widgetは必ずbuild()というメソッドをオーバーライドして、
  // 戻り値として、画面に表示したいWidgetを返す
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      home: new MyHomePage(),
    );
  }
}

//-------------------------------------
// StatefulWidget: 実際の画面
// 常に固定の画面部品を表示させたい時 = StatelessWidgetを使う
// 状態によって画面部品の表示を変化させたい時 = StatefulWidgetとStateを使う
class MyHomePage extends StatefulWidget {
  // StatelessWidgetと違って、build()メソッドは持っていない
  // そのかわりに、createState()メソッドをオーバーライドして、build()メソッドを持つStateインスタンスを返してあげる
  @override
  _MyHomePageState createState() {
    return new _MyHomePageState();
  }
}

// MyHomePageクラスの相方: _MyHomePageStateクラス
// StatefulWidgetの場合は、このStateに主な処理を書いていく
class _MyHomePageState extends State<MyHomePage> {
  // 現在のカウンター値を保持する変数
  int _counter = 0;

  // ボタンが押されたときの処理
  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  // 画面に描画するWidgetを返す
  @override
  Widget build(BuildContext context) {
    // Scaffold = タイトル部分(appBar)とその下の部分(body)、浮遊するボタン(FloatingActionButton)を持つWidget
    // Text = 文字列を描画するWidget
    // Center = childで渡されてきたWidgetの表示位置を調整するWidget
    // Column = childrenで渡されてきた複数のWidgetを、縦並びに表示するWidget
    // FloatingActionButton = 浮遊する丸いボタンを表示するWidget
    return new Scaffold(
      appBar: new AppBar(
        title: new Text('Flutter Demo Home Page'),
      ),
      body: new Center(
        child: new Column(
          mainAxisAlignment: MainAxisAlignment.center, // 中央寄せ
          children: <Widget>[
            new Text(
              'You have pushed the button this many times:',
            ),
            new Text(
              _counter.toString(),
              style: new TextStyle(fontSize: 34.0),
            ),
          ],
        ),
      ),
      floatingActionButton: new FloatingActionButton(
        onPressed: _incrementCounter, // ボタンを押された時に実行するメソッドを指定
        child: new Icon(Icons.add), // ボタンに表示する「+」マークを指定
      ),
    );
  }
}

  • 「描画したいWidgetを入れ子状に定義すると、それが画面になる」イメージ
  • 「実際に画面に描画するWiget」と「画面には直接描画されないけど、他のWidgetのレイアウトなどを助けるWidget」の2種類に大別される
  • 実際に画面に描画するWiget
    • Text
    • FloatingActionButton
    • Icon など
  • 画面には直接描画されないけど、他のWidgetのレイアウトなどを助けるWidget
    • MaterialApp
    • Scaffold
    • Center
    • Column など

2. ToDoリストを表示させるように改造してみる

主な修正は2つ

  • ToDoリストの1項目に相当する、Entryクラスを新たに定義してみる
  • _MyHomePageStateクラス内をごっそり、リストが表示されるように書き換えてみる
import 'package:flutter/material.dart';

//-------------------------------------
// メイン関数: 全てはここから始まる!
void main() {
  // アプリの起点となるrunApp()関数の引数に、
  // Widgetを渡してあげると、それが画面の起点となって表示される
  runApp(new MyApp());
}

//-------------------------------------
// StatelessWidget: アプリのルート画面
// MyAppは実際には画面を持っておらず、その中身に描画させている
class MyApp extends StatelessWidget {
  // Widgetは必ずbuild()というメソッドをオーバーライドして、
  // 戻り値として、画面に表示したいWidgetを返す
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      home: new MyHomePage(),
    );
  }
}

//-------------------------------------
// StatefulWidget: 実際の画面
// 常に固定の画面部品を表示させたい時 = StatelessWidgetを使う
// 状態によって画面部品の表示を変化させたい時 = StatefulWidgetとStateを使う
class MyHomePage extends StatefulWidget {
  // StatelessWidgetと違って、build()メソッドは持っていない
  // そのかわりに、createState()メソッドをオーバーライドして、build()メソッドを持つStateインスタンスを返してあげる
  @override
  _MyHomePageState createState() {
    return new _MyHomePageState();
  }
}

// TODO項目
class Entry {
  // ラベル文言
  String label;
  // チェック状態
  bool isChecked;

  Entry({this.label, this.isChecked = false});
}

// MyHomePageクラスの相方: _MyHomePageStateクラス
// StatefulWidgetの場合は、このStateに主な処理を書いていく
class _MyHomePageState extends State<MyHomePage> {
  // TODOリスト
  List<Entry> entries = [
    new Entry(label: 'あへあへ', isChecked: true),
    new Entry(label: 'どんどん'),
  ];

  // 画面に描画するWidgetを返す
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text('Flutter Demo Home Page'),
      ),
      body: ListView.builder(
        itemCount: entries.length,
        itemBuilder: (BuildContext context, int index) {
          return Row(
            children: <Widget>[
              Checkbox(
                value: entries[index].isChecked,
                onChanged: null,
              ),
              Text(entries[index].label),
            ],
          );
        },
      ),
    );
  }
}
  • ここまでできたら、entriesに値を定義してみる
  • Stateはホットリロードが効かない(Stateの状態は保持される)ので、ここではHot Restartを利用する
  // TODOリスト
  List<Entry> entries = [
    new Entry(label: 'あへあへ', isChecked: true),
    new Entry(label: 'どんどん'),
  ];