【Flutter】MapをListに変換して、ListViewで表示する

image

Version

  • Flutter 2.8.1
  • Dart 2.14.4

はじめに

今回のコードはカウンターアプリをもとに新しいアプリを作る続きと関連しているので、よかったらそちらも参考にしてみてください。 初心者のうちは、Mapとは,Listとは何か、から始まって、Listから必要な要素を取り出す、Mapから必要なkeyやvalueを取り出す、MapをListに変換する、変換したものをListViewで表示する、等々なかなかスムーズにできないものです。 今回もカウンターアプリのコードを基本にMapデータをlistデータに変換してListViewウイジットで表示するという簡単なアプリを作ってみたので紹介します。

コード全文

まずはコード全文です

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  
  State<StatefulWidget> createState() {
    return ListState();
  }
}

class ListState extends State<MyHomePage> {
  Map<String, String> _japaneseMlbPlayers = {
    'Shohei Ohtani': 'Los Angeles Angels',
    'Yu Darvish': 'San Diego Padres',
    'Kenta Maeda': 'Minnesota Twins',
    'Shogo Akiyama': 'Cincinnati Reds',
    'Yoshi Tsutsugo': 'Pittsburgh Pirates',
    'test1': 'test1',
    'test2': 'test2',
  };
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter = (_counter + 1) % _japaneseMlbPlayers.length;
      print(_counter);
    });
  }

  
  Widget build(BuildContext context) {
    final listJmp = _japaneseMlbPlayers.entries
        .map((e) => JapaneseMlbPlayer(e.key, e.value))
        .toList();

    for (int i = 0; i < listJmp.length; i++) {
      print(listJmp[i].name);
      print(listJmp[i].team);
    }

    return Scaffold(
      appBar: AppBar(
        title: Text("Japanese MLB Player"),
      ),
      body: ListView.builder(
        itemBuilder: (BuildContext context, int index) {
          return Container(
            child: ListTile(
              title: _textWidget(listJmp, index, _counter, 'name'),
              subtitle: _textWidget(listJmp, index, _counter, 'team'),
            ),
          );
        },
        itemCount: _japaneseMlbPlayers.length,
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}

class JapaneseMlbPlayer {
  String name;
  String team;

  JapaneseMlbPlayer(this.name, this.team);
}

Widget _textWidget(List list, int index, int counter, String key) {
  if (key == 'name') {
    return Text(
      list[index].name,
      style:
          index == counter ? TextStyle(color: Colors.blue, fontSize: 28) : null,
    );
  }
  if (key == 'team') {
    return Text(
      list[index].team,
      style:
          index == counter ? TextStyle(color: Colors.red, fontSize: 28) : null,
    );
  } else {
    return Text('nothing');
  }
}

コード解説

MapからList への変換

Listを入れるModelクラスとして、JapaneseMlbPlayerを用意します。 <Map型>.entries.map((e) => <Modelクラス>(e.key, e.value)).toList();で、Map からListに変換することができます。

  // リストを入れるModelクラス
  class JapaneseMlbPlayer {
  String name;
  String team;

  JapaneseMlbPlayer(this.name, this.team);
  }

  // Map => List
  final listJmp = _japaneseMlbPlayers.entries
      .map((e) => JapaneseMlbPlayer(e.key, e.value))
      .toList();

  // Listから要素を取り出す
  for (int i = 0; i < listJmp.length; i++) {
    print(listJmp[i].name);
    print(listJmp[i].team);
  }

ListTile表示用_textWidgetを作る

keynameが指定されたとき、teamが指定されたときで分岐させ、indexの値とcounterの値が同じときは、Textの色とサイズが変更される_textWidgetを作成。

Widget _textWidget(List list, int index, int counter, String key) {
  if (key == 'name') {
    return Text(
      list[index].name,
      style:
          index == counter ? TextStyle(color: Colors.blue, fontSize: 28) : null,
    );
  }
  if (key == 'team') {
    return Text(
      list[index].team,
      style:
          index == counter ? TextStyle(color: Colors.red, fontSize: 28) : null,
    );
  } else {
    return Text('nothing');
  }
}

ListTileに,nameteamを表示する

_textWidgetを使って、ListTiletitle:subtitle:nameteamを表示する。

child: ListTile(
        title: _textWidget(listJmp, index, _counter, 'name'),
        subtitle: _textWidget(listJmp, index, _counter, 'team'),
        ),

floatingActionButtonを押すと、Textの色とフォントサイズが順番に変化する

_incrementCounter()を定義し、floatingActionButtonが押されるごとに呼び出される。

  // Listの要素数に応じてカウントする関数
  void _incrementCounter() {
    setState(() {
      _counter = (_counter + 1) % _japaneseMlbPlayers.length;
      print(_counter);
    });
  }

  // ボタンを押すたびに_incrementCounterが呼出されるようにする。
  floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),


まとめ

以上簡単ですが、MapからListへ変換して表示するアプリでした。

参考:https://qiita.com/7_asupara/items/01c29c006556e89f5b17

お知らせ

11月5日開催のアプリ開発講座の参加者募集中!!

11月5日開催のアプリ開発講座の参加者募集中!!

11月5日にアプリ開発講座を開催します!会場は岐阜県美濃加茂市のコワーキングスペース「こやぁね」です。興味のある方は是非ご参加ください!

Read More
可茂IT塾ではFlutterインターンを募集しています!

可茂IT塾ではFlutterインターンを募集しています!

可茂IT塾ではFlutterインターンを募集しています!可茂IT塾のエンジニアの判断で、一定以上のスキルをを習得した方には有給でのインターンも受け入れています。

Read More

お知らせ

11月5日開催のアプリ開発講座の参加者募集中!!

11月5日開催のアプリ開発講座の参加者募集中!!

11月5日にアプリ開発講座を開催します!会場は岐阜県美濃加茂市のコワーキングスペース「こやぁね」です。興味のある方は是非ご参加ください!

Read More
可茂IT塾ではFlutterインターンを募集しています!

可茂IT塾ではFlutterインターンを募集しています!

可茂IT塾ではFlutterインターンを募集しています!可茂IT塾のエンジニアの判断で、一定以上のスキルをを習得した方には有給でのインターンも受け入れています。

Read More