本記事はWordleクローンアプリ開発日記のpart2になります
以前の記事:【アプリ開発日記】アプリを開発するにあたっての流れとコツ【part1】
Widgetを自作する
Wordleクローンアプリでは、UIを大きく2つのWidgetに分けられます。
- キーボード
- 入力した文字を表示する欄
本記事では、キーボードのWidgetを作成します。
ファイルを分けてみる
main.dartのファイルにすべて書いてしまうと1ファイルが肥大化してしまう原因となるため、キーボードのWidgetについては別ファイルにしようと思います。
softwarekeyborad.dartというファイルを作成し、ここにコードを作成していきます。
レイアウト設計
キーボードの1文字のボタンは同サイズで、Containerをそのまま並べてやれば良いと考えました。また、1行に表示する内容をまとめられるよう、1行ごとに表示する文字を別途定義しました。
final List<String> firstLine = ['Q','W','E','R','T','Y','U','I','O','P']; final List<String> secondLine = ['A','S','D','F','G','H','J','K','L']; final List<String> thirdLine = ['ENTER','Z','X','C','V','B','N','M','DEL'];
今回はリストをfinalで宣言することで1行分のデータを固定できているように見えますが、この宣言の仕方ではリストの中身を書き換えることができます。具体的には以下のコードを実行すると中身を書き換えられることが確認できると思います。「finalを付与した変数に対してListを代入することが出来ない」というだけで、中身自体は更新できてしまうのです(今回は直接操作することが無いので無視しますが、そういった可能性があるという点については注意しましょう)。
firstLine[1] = 'aaaaaa';
次に、1キーを構成するWidgetとキーボード全体を構成するWidgetを定義しました。1文字ずつWidgetを生成すると同じコードをたくさん書くことになってしまうため、文字のリストをfor分で回してWidget一覧を生成するcreateLineメソッドを作成しました。
また、1キーを構成するKeyButtonクラスでは、GestureDetectorを使ってユーザ操作を検知できるようにしています。今回はキーボードWidget作成のみのため、onTap内で何も行わないようになっていますが、今後の実装のことを考えてif分でタップされたキーを判別するようにしています。(ENTERとDELは他のキーと異なる処理を行うため)
import 'package:flutter/material.dart'; final List<String> firstLine = ['Q','W','E','R','T','Y','U','I','O','P']; final List<String> secondLine = ['A','S','D','F','G','H','J','K','L']; final List<String> thirdLine = ['ENTER','Z','X','C','V','B','N','M','DEL']; class SoftwareKeyBoard extends StatelessWidget { const SoftwareKeyBoard({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Column( children: [ Row( mainAxisAlignment: MainAxisAlignment.center, children: createLine(firstLine) ), Row( mainAxisAlignment: MainAxisAlignment.center, children: createLine(secondLine) ), Row( mainAxisAlignment: MainAxisAlignment.center, children: createLine(thirdLine) ), ], ); } /// 文字一覧からKeyButtonのリストを生成する List<KeyButton> createLine(List<String> list) { List<KeyButton> buttonList = []; for (String char in list) { buttonList.add(KeyButton(char: char)); } return buttonList; } } class KeyButton extends StatelessWidget { final String char; const KeyButton({Key? key, required this.char}) : super(key: key); @override Widget build(BuildContext context) { Widget w = Text( char, style: const TextStyle( fontSize: 12, color: Colors.black, decoration: null, ), ); int width = 25 + 5 * char.length; // enter delように長さを可変に return GestureDetector( onTap: () { if (char == 'ENTER') { // TODO Enterが押された時のふるまい } else if (char == 'DEL') { // TODO Deleteが押された時の振る舞い } else { // キーが押された時の振る舞い } }, child: Container( margin: const EdgeInsets.all(4), decoration: BoxDecoration( color: Colors.grey[350], borderRadius: BorderRadius.circular(3), ), width: width.toDouble(), height: 45, alignment: Alignment.center, child: w, ), ); } }
part3はこちら
コメントを残す