
マイケル
みなさんこんにちは!
マイケルです!
マイケルです!

エレキベア
こんにちクマ〜〜〜

マイケル
今回は気分転換でFlutterを触ってみました。
作ったのは下記のような、シンプルな英単語学習アプリになります!
作ったのは下記のような、シンプルな英単語学習アプリになります!

エレキベア
Flutter久しぶりクマ〜〜〜

マイケル
内容としては単純なものになりますが、データはGoogleスプレッドシート上で作成したものをAPI経由で取得するようにしています!

エレキベア
DBの代わりにスプレッドシートを使った感じクマね

マイケル
今回はこのアプリの実装内容について解説していこうと思います!
ソースコードの方はGitHubにも上げていますので、こちらもよければご参照ください!
ソースコードの方はGitHubにも上げていますので、こちらもよければご参照ください!
GitHub – masarito617/flutter-english-study-app-sample

エレキベア
この量だとコードを読むのが一番手っ取り早そうクマね

マイケル
なお、Flutterのバージョンは3.3.9を使用しています。
バージョンによって差異が生じる可能性があるため、そちらはご了承ください!
バージョンによって差異が生じる可能性があるため、そちらはご了承ください!
作成するアプリ
画面構成

マイケル
今回作成したアプリは大きく
・タイトル画面
・単語選択画面
の2つの画面から出来ています。
・タイトル画面
・単語選択画面
の2つの画面から出来ています。
タイトル画面
単語選択画面

マイケル
英単語の日本語訳を4択から選ぶ構成となっています。

エレキベア
シンプルなクイズ形式のアプリクマね
Googleスプレッドシート

マイケル
そして一点工夫した点としては、英単語データはGoogleスプレッドシート上から読み込むようにしたことです。
下記のように英単語と日本語訳を設定しておくことで読み込むことができます。
下記のように英単語と日本語訳を設定しておくことで読み込むことができます。

エレキベア
これなら手軽に問題の編集や追加が行えそうクマね

マイケル
読込はGoogle Sheets APIというAPIを使用していました。
こちらも詳細は後ほど記載します!
こちらも詳細は後ほど記載します!
フォルダ構成

マイケル
ソースコードのフォルダ構成は下記のようにしています。
main.dartとpages配下のdartファイルがメインとなります。
main.dartとpages配下のdartファイルがメインとなります。
↑ソースコードのフォルダ構成

エレキベア
このボリュームだとコンパクトクマね
タイトル画面

マイケル
それでは実装を見ていきます。
まずはタイトル画面の実装になります。
まずはタイトル画面の実装になります。
タイトル画面全体の実装

マイケル
main.dartファイルが処理の起点となっていて、ここで全体のテーマを設定しています。
homeにtitle_page.dartのTitlePage()を指定することでタイトル画面を表示します。
homeにtitle_page.dartのTitlePage()を指定することでタイトル画面を表示します。
↑main処理には全体のテーマを設定

エレキベア
アプリ全体の設定をしているクマね

マイケル
TitlePageはStatefulWidgetとして定義していて、大枠となるWidget構成やボタン押下時の処理を記述しています。
↑タイトル画面をStatefulWidgetとして定義

マイケル
HalfScreenAreaというのは画面半分サイズのエリアを取得するよう、共通のWidgetとして定義したものです。
こちらは問題選択画面でも使用します。
こちらは問題選択画面でも使用します。
↑画面半分のエリア定義

エレキベア
画面を半々で作っているクマね

マイケル
上半分をタイトルテキストエリア、下半分をタイトルボタンエリアとしてStatelessWidgetとして分割しています。
こちらパラメータやボタン押下処理を受け取って設定しているだけですね。
こちらパラメータやボタン押下処理を受け取って設定しているだけですね。
↑WidgetはそれぞれStatelessWidgetとして分離

エレキベア
一つにまとめて書いてしまうとかなり長くなってしまうクマからね
ボタン押下処理

マイケル
各ボタンの押下処理は下記のようになっています。
シャッフルするかのチェックボックスは単純にフラグを切り替えるだけで、STARTボタン押下時には英単語データを取得して単語選択ページに遷移するよう実装しています。
シャッフルするかのチェックボックスは単純にフラグを切り替えるだけで、STARTボタン押下時には英単語データを取得して単語選択ページに遷移するよう実装しています。
↑各ボタンの処理

エレキベア
setStateで状態を変更するために、
StatefullWidget内で処理を記述する必要があるクマね
StatefullWidget内で処理を記述する必要があるクマね

マイケル
アクションも分離する方法はあるだろうけど、この量ならこれでも充分そうだね
英単語データの取得処理についてはこの後解説します!
英単語データの取得処理についてはこの後解説します!
Gooogleスプレッドシートからのデータ取得

マイケル
Googleスプレッドシートからデータを取得する処理に関しては下記のように実装しています。
一般的なAPI取得の処理で、指定URLからJSONレスポンスを取得する実装となっています。
一般的なAPI取得の処理で、指定URLからJSONレスポンスを取得する実装となっています。
↑英単語データの取得処理

マイケル
リクエストにはhttpパッケージが必要なため、pubspac.yamlに指定してflutter pub getしておく必要があります。
↑httpパッケージを追加

エレキベア
API実行は定番クマね

マイケル
そして肝心のデータ取得のURLについてですが、今回はGoogle Sheets APIの
https://sheets.googleapis.com/v4/spreadsheets/${spreadsSheetsUrl}/values/${sheetName}?key=${apiKey}
の形式でリクエストしています。
settings/googleapi_settings.dartに各値からURLを生成するようにしてあるので、もし動かす場合はこちらに各自のスプレッドシートID、シート名、APIキーを設定しましょう。
https://sheets.googleapis.com/v4/spreadsheets/${spreadsSheetsUrl}/values/${sheetName}?key=${apiKey}
の形式でリクエストしています。
settings/googleapi_settings.dartに各値からURLを生成するようにしてあるので、もし動かす場合はこちらに各自のスプレッドシートID、シート名、APIキーを設定しましょう。
↑Google Sheets API のURL生成

エレキベア
この辺は各々設定する必要があるクマね

マイケル
それぞれの取得方法について簡単に書いておくと、
・スプレッドシートID
→スプレッドシートを公開した際のURLから取得
・シート名
→スプレッドシートで読み込むシート名
・APIキー
→Google Cloudでプロジェクトを生成してGoogle Sheets APIを有効化して認証情報から生成
からそれぞれ取得することができます。
・スプレッドシートID
→スプレッドシートを公開した際のURLから取得
・シート名
→スプレッドシートで読み込むシート名
・APIキー
→Google Cloudでプロジェクトを生成してGoogle Sheets APIを有効化して認証情報から生成
からそれぞれ取得することができます。

エレキベア
これならサクッと作れそうクマね
単語選択画面

マイケル
そして次は単語選択画面です!
こちらは画面内で、
・選択前
・選択後
・結果表示
の3つの表示状態に切り替わる内容になっています。
こちらは画面内で、
・選択前
・選択後
・結果表示
の3つの表示状態に切り替わる内容になっています。

エレキベア
状態を管理して表示を分ける必要があるクマね
単語選択画面全体の実装

マイケル
大枠のWidget表示については下記のようになっています。
Enum型でQuestionDisplayStateとして状態を管理し、その状態を監視して表示を切り替えています。
Enum型でQuestionDisplayStateとして状態を管理し、その状態を監視して表示を切り替えています。
↑QuestionDisplayStateの状態によって表示するWidgetを切り替える

エレキベア
それぞれのWidgetについてはまた分割しているクマね
選択前の初期表示

マイケル
まずは選択前の初期表示から見ていきます。

マイケル
こちらはinitState内でタイトル画面から受け取った英単語データから問題と選択リストを生成しています。
↑問題と選択リストの生成

マイケル
選択リストに関しては、答えとなる日本語に加えてランダムで選択した日本語を加えて4つ分生成するようにしてあります。

エレキベア
選択できる日本語も設定したデータから適当に選んでいるクマね

マイケル
問題の表示部分に関してもタイトル画面と同様、画面半分ずつに区切って表示しています。
上半分を問題文エリア、下半分を単語選択ボタンエリアとして定義しました。
問題文に関しては下記のように受け取ったパラメータの表示に加えて、stateも受け取ることで答えも表示できるよう対応しています。
上半分を問題文エリア、下半分を単語選択ボタンエリアとして定義しました。
問題文に関しては下記のように受け取ったパラメータの表示に加えて、stateも受け取ることで答えも表示できるよう対応しています。
↑状態に応じて答えの表示可否を切り替える

マイケル
単語選択ボタン群に関しても、状態からボタンの活性可否やNEXTボタンの表示可否を切り替えるようにしています。
選択時には選んだ日本語をパラメータとして押下処理に渡すようにしています。
選択時には選んだ日本語をパラメータとして押下処理に渡すようにしています。
↑単語選択ボタンの表示

エレキベア
StatelessWidgetでも親から状態を受け取ることで表示を切り替えることができるクマね
選択処理

マイケル
選択処理に関しては、選んだ日本語が合っているかどうかの答え合わせをしています。
NEXTボタンを押下した際には次の問題へ進み、最後の問題の場合には最終的な結果を表示します。
NEXTボタンを押下した際には次の問題へ進み、最後の問題の場合には最終的な結果を表示します。

エレキベア
この辺はシンプルクマね
結果表示

マイケル
そして最終的な結果表示に関しては、カウントした正解数を表示させているだけになります。

エレキベア
この辺は説明不要クマね

マイケル
アプリ全体の解説は以上になります!
流れについては大体分かったのではないでしょうか!
流れについては大体分かったのではないでしょうか!
おわりに

マイケル
というわけで今回はFlutterで簡単なアプリを作ってみました!
どうだったかな??
どうだったかな??

エレキベア
何も考えなくてもある程度UIが綺麗になるのと、
これだけでアプリが作れるのは素晴らしいと思ったクマ〜〜
これだけでアプリが作れるのは素晴らしいと思ったクマ〜〜

マイケル
Flutter感出まくりだけど、パッと作れるから本当楽だね!
ただUI部分のコードが作り上どうしてもインデントが深くなってしまうから、整理してなるべく可読性はよくしておきたいなと思ったよ
ただUI部分のコードが作り上どうしてもインデントが深くなってしまうから、整理してなるべく可読性はよくしておきたいなと思ったよ

エレキベア
この規模ならいいクマが、
大きなアプリを作る場合はアーキテクチャもちゃんと調べた方がよさそうクマね
大きなアプリを作る場合はアーキテクチャもちゃんと調べた方がよさそうクマね

マイケル
楽しかったからまた触ってみよう!
それでは今日はこの辺で!!
アデューー!!
それでは今日はこの辺で!!
アデューー!!

エレキベア
クマ〜〜〜〜
【Flutter3】Googleスプレッドシートと連携した英単語学習アプリを作る 〜完〜