【Flutter】配列と繰り返し文を使ってUIを羅列する

目次

概要

表示するUIの数が多くなってくると、一つ一つオブジェクトを羅列していくのは困難になる。
加えて、今後のメンテナンスもしづらくなる。

そのため、今回は複数のボタンを配列に格納してfor文でまとめて羅列してみよう。

ソースコード

アプリ実行部分

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

import 'ArrayButton/ButtonArrayView.dart';

void main() {
  runApp(ProviderScope(child: MyApp()));
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepOrange),
        useMaterial3: true,
      ),
      home: const ButtonArrayView(title: 'Flutter Demo Home Page'),
    );
  }
}

View表示部分

import 'package:concentration/Common/TrumpMark.dart';
import 'package:flutter/material.dart';

import '../Common/TrumpCard.dart';

class ButtonArrayView extends StatefulWidget {
  const ButtonArrayView({super.key, required this.title});
  final String title;

  @override
  State<ButtonArrayView> createState() => _ButtonArrayViewState();
}

class _ButtonArrayViewState extends State<ButtonArrayView> {
  final maxNumber = 13;
  List<OutlinedButton> trumpButtons = [];

  @override
  Widget build(BuildContext context) {

    for (int number = 0; number < maxNumber; number++) {
      var trump = TrumpCard((false), number + 1, TrumpMark.spade);

      var trumpButton = OutlinedButton(
          onPressed: () { print("${trump.number}"); },
          style: OutlinedButton.styleFrom(
            backgroundColor: Colors.white10,
            foregroundColor: Colors.black,
          ),
          child: Text("${trump.mark.trumpMarkString} ${trump.number}")
      );

      trumpButtons.add(trumpButton);

    }

    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              '好きなカードを選択してください',
            ),
            for(OutlinedButton trumpButton in trumpButtons)
              trumpButton
          ],
        ),
      ),
    );
  }
}

スクリーンショット

詳細

今回の件を実装するには、まず以下の項目ができている必要がある。

  • 配列
  • 繰り返し文

配列の作り方

まずは配列の作り方について。
配列を作る際の公式は以下の通り。

List</* 型名(クラス・オブジェクト名) */> /* 配列名 */ = [/* 格納する値 */];

日本語に直すと以下の通り。

複数の「型名(クラス・オブジェクト名)」のデータをまとめたものを「配列名」と名付け、
その配列を生成すると同時に「格納する値」を格納する

今回の場合は以下のようになっている。

List<OutlinedButton> trumpButtons = [];
項目名内容
型名(クラス・オブジェクト名)OutlinedButton
配列名trumpButtons
格納する値(初期値)なし([ ]の中に要素がないため)

まずはこれで配列を作れた。おめでとう。

配列に要素を追加する

配列は空っぽのままでは使えない。
なので、生成した配列に要素を追加しよう。追加の仕方は以下の通り。

/* 配列名 */.add(/* 格納する値 */);

日本語に直すと以下の通り

配列名」に「格納する値」を追加(add)する

今回の場合は以下のように設定されている。

trumpButtons.add(trumpButton);

OutlinedButton型のオブジェクト(データ)を格納している配列「trumpButtons」にOutlinedButton型のオブジェクト(データ)「trumpButton」を追加(add)する。

こうすることで配列にボタンを追加している。

繰り返し文

今回はfor文で紹介する。
繰り返し文は今回二種類出てくる。

  • 指定した条件が成立している間繰り返す(指定した回数分繰り返すのはこちら)
  • 配列の要素数分だけ繰り返す

指定した条件が成立している間繰り返す

この繰り返し文の基本形はこちら

for (/* 初期化処理 */; /* 条件式 */ ; /* {}内の処理が終わった時に行われる処理 */) {
  /* 条件式が満たされている場合に行う処理 */
}
/* 「条件式」が満たされなくなった時に行われる */

順番に書くとこんな感じ。

  1. 初期化処理({}内の処理が行われる前に行われる)」を行う
  2. 条件式」が満たされているかどうかを確認する
  3. 以下で分岐する
    • 条件式」が満たされている場合、「条件式が満たされている場合に行う処理({}内の処理)」を行う。
    • 条件式」が満たされていない場合、『「条件式」が満たされなくなった時に行われる』の部分以降の処理を行う。(繰り返し処理終了)
  4. {}内の処理が終わった時に行われる処理」を行い、2に戻る。

今回は以下のように行われている。

final maxNumber = 13;
List<OutlinedButton> trumpButtons = [];

for (int number = 0; number < maxNumber; number++) {
  var trump = TrumpCard((false), number + 1, TrumpMark.spade);

  var trumpButton = OutlinedButton(
      onPressed: () { print("${trump.number}"); },
      style: OutlinedButton.styleFrom(
        backgroundColor: Colors.white10,
        foregroundColor: Colors.black,
      ),
      child: Text("${trump.mark.trumpMarkString} ${trump.number}")
  );

  trumpButtons.add(trumpButton);
}
項目名内容
初期化処理int number = 0
条件式number < maxNumber
{ }内の処理が終わった時に行われる処理number++
条件式が満たされている場合に行う処理5~16行目の処理

今回の場合、maxNumberは13と設定されているので、日本語に直すと以下のようになっている。

  1. 初期化処理として整数のデータを格納する変数「number」に0を格納する(代入する)。
  2. numberとmaxNumber(13)を比較して、numberの方が小さければすぐ下の{ }内の処理を行う。(そうでなければすぐ下の{ }内の処理を行わずに{ }以降の処理を行う)
  3. 以下の1~3の処理(条件式が満たされている場合に行う処理の「5~16行目の処理」)を行う
    1. TrumpCardのオブジェクトを「trump」という名前で生成する
    2. 7~14行目でOutlinedButton(外枠付きのボタン)のオブジェクトを「trumpButton」という名前で生成する
    3. OutlinedButton型を格納した配列「trumpButtons」に「trumpButton」を追加(add)する
  4. { }内の処理が終わった時に行われる処理「number++」(numberに1を足す)を行う
  5. 2に戻る。

こうすることでOutlinedButton型を格納した配列「trumpButtons」に13個のOutlinedButton(外枠付きのボタン)のオブジェクトを格納できる。

配列の要素数分だけ繰り返す

for文には配列の要素数だけ繰り返すという方法もある。

for(/* 配列の型名(クラス・オブジェクト名) */ /* 配列名から取り出した要素名 */ in /* 配列名 */) {
  /* 配列名から要素を取り出した時に行われる処理 */
}

今回の場合は以下のようになっている。
また、今回はボタンなどの画面の部品(UI)を並べる場合は「{ }」は使わず、配列名から取り出した要素名を記載するのみになっている。

for(OutlinedButton trumpButton in trumpButtons)
  trumpButton
項目名内容
配列の型名(クラス・オブジェクト名)OutlinedButton(trumpButtonsはOutlinedButtonのデータを格納した配列のため)
配列名から取り出した要素名trumpButton
配列名trumpButtons
配列名から要素を取り出した時に行われる処理trumpButton(今回の場合は画面の部品を並べるだけなので、「trumpButton」のみで良い)

ちなみに、この「trumpButton」は配列「trumpButtons」のデータを先頭から順番に取り出した値が格納されている。

つまり、1回目の処理ではtrumpButtonsの最初の要素が、2回目の処理ではtrumpButtonsの二番目の要素が格納されている。

参考ページ

  • 「」