1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

[Flutter]スプレッド演算子を使って動的なWidgetを簡単に生成する方法

Posted at

はじめに

FlutterでWidgetをList配列でループさせて表示させようと無邪気にfor文を使うとまんまとエラーになり、ハマるので簡単な解決方法をメモします。
Dart言語で用意されているスプレッド演算子(...)を使ってFlutterで動的にWidgetを作成することができます。
(スプレッド演算子を使うことでスタイリッシュに記述できます)

無邪気にfor文でList配列をループさせてみる

List配列を用意します

List<Widget> textWidgets() {
    return [
        Text('hogehoge1'),
        Text('hogehoge2'),
        Text('hogehoge3'),
    ];
}

List配列をforループさせて実行させます

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('With Spread Operator'),
        ),
        body: Column(
          children: [
              for(int i = 0; i < textWidgets().length; i++) {
                textWidgets()[i]
              }
          ],
        ),
      ),
    );
  }
}

実行結果
コンパイルエラーになります

Error: A value of type 'Set<Widget>' can't be assigned to a variable of type 'Widget'.

## 原因
Flutterでは動的にWidgetを配置する場合にはfor文を純粋に使うだけではうまくいきません。(これはFlutterの仕様でそうなっています)

解決策1:スプレッド演算子を使う(for{}...)

for{}...でスプレッド演算子を使って動的に表示することができます(下記コードはエラーにならず、うまく表示されます。)

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('With Spread Operator'),
        ),
        body: Column(
          children: [
              for(int i = 0; i < textWidgets().length; i++) ...{
                textWidgets()[i]
              }
          ],
        ),
      ),
    );
  }
}

解決策2:スプレッド演算子を使う(Listに...)

そのままListにスプレッド演算子を使うこともできます。(下記コードはエラーにならず、うまく表示されます。)

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('With Spread Operator'),
        ),
        body: Column(
          children: [
            ...textWidgets()
          ],
        ),
      ),
    );
  }
}

解決策3:スプレッド演算子を使う(...[]for(){})

配列にスプレッド演算子を使って動的に表示することができます(下記コードはエラーにならず、うまく表示されます。)

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('With Spread Operator'),
        ),
        body: Column(
          children: [
              ...[
                for(int i = 0; i < textWidgets().length; i++) textWidgets()[i],
              ]
          ],
        ),
      ),
    );
  }
}

スプレッド演算子を使わない場合

基本的に動的にWidgetを表示する方法はスプレッド演算子を使う方法しかFlutterはなさそうです。そもそも連続して表示する場合のコンテンツとしてListViewやGridViewなどがあるためそれで大概は解決します。しかしプログラムして同類のコンテンツをループさせたいシチュエーションはあるためその時のために覚えておくと便利です。

スプレッド演算子を使わない方法

  • for文を使わずにそのまま配列のWidgetをインデックスを指定して表示する
  • ListViewなどを使って動的に表示する

さいごに

Flutterも然り、宣言型UIのプログラムはレイアウトとロジックを組み合わせる仕組み上、どうしても独特のルールが存在します。SwiftUI,JetpackComposeも同様にそれぞれ強めのルールがあるため個別にルールとして記憶して対応するのが良いでしょう。(内部的に深く追求するのもいいと思います。)

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?