- ホーム
- ブログ
- 【Flutter】カウンターアプリから初めての自作アプリ
- カウンターアプリから新しいアプリを作る(初心者向け)続き
この記事は、【 可茂IT塾 Advent Calendar 2021 】の20日目の記事です。
前回、カウンターアプリを使って組み込み型を操作するアプリを作りました。 それをもとに少し修正してみたいと思います。内容はFloatingActionButtonを押すたびにListとMapで表示されていた要素とkey、valueが一つずつ順番に色とフォントを変えて表示されます。
// List部分
Text(_string,
style: TextStyle(color: Colors.blue),
),
// Map部分
Text(_japaneseMlbPlayers.toString(),
style: TextStyle(color: Colors.blue),
),
これをRichTextを使ってフォントの色とサイズを変えようと思い、以下のようなコードに修正しました。
// 途中省略
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を変更する
);
}
// 途中省略
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を一つ一つ定義していたので、長いコードになってしまいました。ちょっと外に出すとコードが簡潔になりますね。 もっと効率のよい書き方もあるような気がしますが、少しずつ覚えていきたいと思います。
可茂IT塾ではFlutterインターンを募集しています!可茂IT塾のエンジニアの判断で、一定以上のスキルをを習得した方には有給でのインターンも受け入れています。
Read More可茂IT塾ではFlutterインターンを募集しています!可茂IT塾のエンジニアの判断で、一定以上のスキルをを習得した方には有給でのインターンも受け入れています。
Read More