カウンターアプリから新しいアプリを作る(初心者向け)続き

image

この記事は、【 可茂IT塾 Advent Calendar 2021 】の20日目の記事です。

Version

  • Flutter 2.6.0
  • Dart 2.14.4

カウンターアプリをもとに新しいアプリを作る(続き)

前回、カウンターアプリを使って組み込み型を操作するアプリを作りました。 それをもとに少し修正してみたいと思います。内容はFloatingActionButtonを押すたびにListとMapで表示されていた要素とkey、valueが一つずつ順番に色とフォントを変えて表示されます。

コード修正

修正前

// List部分
Text(_string,
     style: TextStyle(color: Colors.blue),
    ),
// Map部分
Text(_japaneseMlbPlayers.toString(),
     style: TextStyle(color: Colors.blue),
    ),

これをRichTextを使ってフォントの色とサイズを変えようと思い、以下のようなコードに修正しました。

修正(List部分)

// 途中省略
showListElement(_splitString, _fiveCounter),
// 途中省略
Widget showListElement(List list, int counter) {
  return RichText(
    text: TextSpan(
      style: TextStyle(color: Colors.black),
      children: [
        listElementTextSpan(list, 0, counter),
        listElementTextSpan(list, 1, counter),
        listElementTextSpan(list, 2, counter),
        listElementTextSpan(list, 3, counter),
        listElementTextSpan(list, 4, counter),
      ],
    ),
  );
}

listElementTextSpan(List list, int element, int counter) {
  return TextSpan(
    text: '${list[element]}',
    style:
        counter == element ? TextStyle(color: Colors.blue, fontSize: 24) : null,
        // カウンターの数字とelementの数字が同じときにTextStyleを変更する
  );
}

修正(Map部分)

// 途中省略
showMapElement(_japaneseMlbPlayers, _fiveCounter),
// 途中省略
Widget showMapElement(Map map, int counter) {
  return RichText(
    text: TextSpan(
      style: TextStyle(color: Colors.black),
      children: [
        mapKeyElementTextSpan(map, 0, counter),
        mapValueElementTextSpan(map, 0, counter),
        mapKeyElementTextSpan(map, 1, counter),
        mapValueElementTextSpan(map, 1, counter),
        mapKeyElementTextSpan(map, 2, counter),
        mapValueElementTextSpan(map, 2, counter),
        mapKeyElementTextSpan(map, 3, counter),
        mapValueElementTextSpan(map, 3, counter),
        mapKeyElementTextSpan(map, 4, counter),
        mapValueElementTextSpan(map, 4, counter),
      ],
    ),
  );
}

mapKeyElementTextSpan(Map map, int element, int counter) {
  return TextSpan(
    text: '${map.keys.elementAt(element)} ',
    style: counter == element
        ? TextStyle(color: Colors.orange, fontSize: 24)
        : null,
    // keyのelementとカウンターの数字が一致したときにTextStyleを変更する
  );
}

mapValueElementTextSpan(Map map, int element, int counter) {
  return TextSpan(
    text: '${map.values.elementAt(element)} ',
    style: counter == element
        ? TextStyle(color: Colors.green, fontSize: 24)
        : null,
    // valueのelementとカウンターの数字が一致したときにTextStyleを変更する
  );
}


これで、カウンターの数字が変化するごとにListとMapの文字の色と大きさが変化するアプリが完成しました。

コード全文

コード全文は以下の通りです。

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() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;
  String _string = 'イヌ サル キジ タヌキ キツネ';
  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',
  };
  bool _isChecked = false;

  void _incrementCounter() {
    setState(() {
      _counter++;
      _isChecked = !_isChecked;
    });
  }

  
  Widget build(BuildContext context) {
    int _fiveCounter = (_counter + 5) % 5;
    List _splitString = _string.split(' ');

    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.start,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: <Widget>[
            SizedBox(
              height: 20,
            ),
            showListElement(_splitString, _fiveCounter),
            SizedBox(
              height: 20,
            ),
            showMapElement(_japaneseMlbPlayers, _fiveCounter),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}

Widget showListElement(List list, int counter) {
  return RichText(
    text: TextSpan(
      style: TextStyle(color: Colors.black),
      children: [
        listElementTextSpan(list, 0, counter),
        listElementTextSpan(list, 1, counter),
        listElementTextSpan(list, 2, counter),
        listElementTextSpan(list, 3, counter),
        listElementTextSpan(list, 4, counter),
      ],
    ),
  );
}

listElementTextSpan(List list, int element, int counter) {
  return TextSpan(
    text: '${list[element]}',
    style:
        counter == element ? TextStyle(color: Colors.blue, fontSize: 24) : null,
  );
}

Widget showMapElement(Map map, int counter) {
  return RichText(
    text: TextSpan(
      style: TextStyle(color: Colors.black),
      children: [
        mapKeyElementTextSpan(map, 0, counter),
        mapValueElementTextSpan(map, 0, counter),
        mapKeyElementTextSpan(map, 1, counter),
        mapValueElementTextSpan(map, 1, counter),
        mapKeyElementTextSpan(map, 2, counter),
        mapValueElementTextSpan(map, 2, counter),
        mapKeyElementTextSpan(map, 3, counter),
        mapValueElementTextSpan(map, 3, counter),
        mapKeyElementTextSpan(map, 4, counter),
        mapValueElementTextSpan(map, 4, counter),
      ],
    ),
  );
}

mapKeyElementTextSpan(Map map, int element, int counter) {
  return TextSpan(
    text: '${map.keys.elementAt(element)} ',
    style: counter == element
        ? TextStyle(color: Colors.orange, fontSize: 24)
        : null,
  );
}

mapValueElementTextSpan(Map map, int element, int counter) {
  return TextSpan(
    text: '${map.values.elementAt(element)} ',
    style: counter == element
        ? TextStyle(color: Colors.green, fontSize: 24)
        : null,
  );
}

まとめ

最初は、RichText内のTextSpanを一つ一つ定義していたので、長いコードになってしまいました。ちょっと外に出すとコードが簡潔になりますね。 もっと効率のよい書き方もあるような気がしますが、少しずつ覚えていきたいと思います。

お知らせ

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

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

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

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

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

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

Read More

お知らせ

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

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

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

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

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

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

Read More