Hondaのエンジン屋が約半年でFlutterで出来るようになったこと

# はじめに

本田技研工業のRoadMovies+チームのフロントエンドを担当している高(こう)と申します。
今回はTechブログ第二弾の投稿となります。

### 簡単に自己紹介

私は下記に紹介する「RoadMovies+」のFlutterでの開発に取り組んでいます。
それまではHonda 四輪車の機種開発を入社以来やっており、
バリバリのエンジン屋でした。(笑)
(プログラミング経験はほとんどありません。大学時代のC言語ぐらい…？)

そんな私が2022年9月からスマホアプリ開発業務としてFlutterを触り始め、
約半年を迎えたタイミングで、どの程度まで実装出来るようになったのか、
公開したてホヤホヤのRoadMovies+(Android版)を例にご紹介していきます！

# TL;DR

- プログラミング初心者が約半年でココまでアプリを作れるようになったよ
- Flutter Android版RoadMovies+での実装実績紹介
- RoadMovies+の設定画面を例に実際どのように書くのか、かる〜く紹介

# RoadMovies+とは(宣伝)

![スクリーンショット 2023-02-21 13.40.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3083860/1a8db753-033c-ce28-e7c9-8bc42a519117.png)
紹介サイト： [https://www.honda.co.jp/appli/roadmoviesplus/](https://www.honda.co.jp/appli/roadmoviesplus/)


これまではiOS版でしかご利用頂けませんでしたが、
Android版も遂に2023/02/23にリリースしました！
（自分で作ったのが世に出てるぅ。。驚）

Android版↓

https://roadmovies.page.link/2eWh


iOS版↓

https://roadmoviesplus.page.link/2eWh


### 何はさておき完成版はこちら

私は主に、起動画面や設定画面、音楽選択時の挙動、タイトル名入力関連などの実装をしています。
出来上がったのが、こんな感じ↓


《起動画面》
![起動画面.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3083860/edecb26e-da3f-94cf-e9c5-add4ced14e35.gif)
アプリ起動時はアプリアイコンを表示する

《設定画面》
![設定画面2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3083860/48c1c65f-24bf-db48-8812-68345740d6fd.gif)
プライバシーポリシーのみ外部ブラウザで表示し、それ以外はアプリ内で表示する

《タイトル編集画面》
![タイトル名編集.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3083860/7bf20a49-b419-a9e3-dff2-70cc553df9a0.gif)
入力値の変更を反映するのみならず、「空欄」や「スペースのみ」が
入力された場合は、元の入力値を表示する仕様

《音楽選択画面》
![音楽選択.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3083860/1fb6a224-5484-9407-edbe-d857ad326e26.gif)
音楽選択前は撮影時の音声のみ(スライダーを左側で保持)となり、
音楽選択後は選択した音楽の音量のみ(スライダーを右側で保持)となる。


# 設定画面の実装

本記事では設定画面のようなUIをFlutterでは、どのように実装しているか簡単に説明します。

RoadMovies+では、「使い方」「利用規約」「よくある質問」はアプリ内で表示しており、
「プライバシーポリシー」のみ外部ブラウザにて表示する仕様となっています。

そこで今回は、「アプリ内で表示する項目」と「外部ブラウザで表示する項目」の
2つのグループに分けて実装していきます。

Flutter Android版での設定画面は下図のようになっていて、`GroupedListView`という
Widgetを用いて、その子要素として`ListTile`を持たせて実装しています。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3083860/823fef42-af10-d595-abeb-977538f3ff13.png" width=30%>


`ListView`の子要素に`ListTile`を持たせても近しいことは出来るのですが、
今回RoadMovies+ではAppBarの下部に「サポート」の文字(上図参考)を表示させるために、
`GroupedListView`を使用しています。

`GroupedListView`は公式のライブラリを使用するので、
下記リンク先の手順に従って、まずインストールします。
公式サイト：[grouped_list | Flutter Package](https://pub.dev/packages/grouped_list/install)

記事投稿時点では下記のバージョンを使用します。

```
dependencies:
  grouped_list: ^5.1.2
```

```dart
class _MyHomePageState extends State<MyHomePage> {

  //設定画面内で表示したい項目をリスト化する
  final List itemList = [
    {'name': '使い方', 'group': 'アプリ内で表示する項目↓'},
    {'name': '利用規約', 'group': 'アプリ内で表示する項目↓'},
    {'name': 'よくある質問', 'group': 'アプリ内で表示する項目↓'},
    {'name': 'プライバシーポリシー', 'group': '外部ブラウザで表示する項目↓'},
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('設定画面のイメージ'),
      ),
      body: GroupedListView<dynamic, String>(

        //GroupedListViewのelementsプロパティに上でリスト化した内容を指定
        elements: itemList,
        groupBy: (element) => (element['group']),

        //GroupedListOrder.ASCで昇順、GroupedListOrder.DESC降順となる
        order: GroupedListOrder.ASC,
        groupSeparatorBuilder: (String value) => Padding(

        //グループ名を基準に周囲にどの程度余白を設けるか設定する
          padding: const EdgeInsets.only(left: 10, top: 30, bottom: 10),
          child: Text(
            value,
            textAlign: TextAlign.left,
            style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
          ),
        ),
        itemBuilder: (context, element) {
          return Card(
            elevation: 10.0,
            margin: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 6.0),
            child: ListTile(
              contentPadding:
                  const EdgeInsets.symmetric(horizontal: 10.0, vertical: 6.0),
              title: Text(element['name']),
              trailing: const Icon(Icons.adb), //trailingで右寄せでアイコン表示 (左寄せはleading)
              onTap: () {
                //ここに項目タップ時の動作を記述する （App内別ページへの遷移や外部ブラウザを開くなど）
              },
            ),
          );
        },
      ),
    );
  }
}

```
↓完成版UI
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3083860/1d3a5380-eab2-723e-f4c6-6c4aaee7a0c2.png" width=30%>

このように、`GroupedListView`を用いることで用途毎に
グループ分けをして項目を表示することが可能となります。

# 結論

- 全くプログラミングを学んだことが無くても、日頃から触っていれば半年で
このレベルまでは実装できるようになる！
- 今回ご紹介できていないですけど、IDE (Android Studio)等の小技を
早めに身に付けるとかなり時短になるので、オススメ！