初心者エンジニアによるAndroidアプリ開発日記④

# まえがき
AndroidStudioでプロジェクトを立ち上げ、フォルダ構成やAndroidStudioの機能を一通り把握できたので、いよいよ実装に入っていきます。ChatGPTに相談し、まずはレイアウトから着手することにしました。

前回は[こちら](https://qiita.com/hukusima65/items/8d3e131a11215091adac)

# 目次
* [概要](#概要)
* [実装する画面](#実装する画面)
* [XMLについて](#xmlについて)
   * [XMLのレイアウト](#xmlのレイアウト)
   * [XMLのオブジェクト](#xmlのオブジェクト)
   * [XMLのレイアウト・Widgetsのプロパティ](#xmlのレイアウトwidgetsのプロパティ)
* [実装](#実装)
   * [タイトル画面](#タイトル画面)
   * [クイズ画面](#クイズ画面)
   * [不正解画面](#不正解画面)
* [終わりに](#終わりに)

---

## 概要
この記事では、国旗当てクイズアプリのレイアウトの実装内容や、調べた内容を記載する。

## 実装する画面
作るものについては[1回目の記事](https://qiita.com/hukusima65/items/2b4af030fdc74942ec48)に記載しました。ここで必要な画面は、以下のようになりそうです。

* タイトル画面
   * スタートボタン付き
* クイズ画面
   * 国旗と、4択の選択肢が表示される
   * 正解を選択すると、次の問題に移動
   * 不正解で、不正解画面を表示
* 不正解画面
   * 「タイトルへ戻る」ボタン付き
   * 正解数が表示される

>ハイスコアの表示や問題のブックマーク機能など、他にも追加したい機能はありますが、初めてのAndroidアプリ開発ということでシンプルなものを作成します。

以上の3つの画面を、ChatGPTに頼りながら実装していきます。

## XMLについて
まず、レイアウトで用いるXMLについて簡単に説明します。resフォルダ内にてXMLは、

```
<レイアウトの種類>
    <オブジェクト1/>
    <オブジェクト2/>
        　:

</レイアウトの種類>
```
となっているようです。タグの中で、文言や空白の範囲などが設定できるようです。

### XMLのレイアウト
* LinearLayout
今回はLinearLayoutのみ使いました。android:orientation="vertical"なら縦方向、"horizontal"なら横方向に、直線的にオブジェクトを配置します。LinearLayout以外のレイアウトに関しては[こちら](https://tech.uzabase.com/entry/2020/04/01/194807)が参考になります。

### XMLのオブジェクト
[こちらの記事](https://qiita.com/mii-chang/items/ee965c1e8826d4e59414)によると、**Widgets**というらしいです。
* ImageView：画像
* TextView：テキスト
* Button：ボタン
* GridLayout：格子状にWidgetsを並べる　など

### XMLのレイアウト・Widgetsのプロパティ
重要と思われるものをざっと列挙します。
* 大きさ関連：layout_width、layout_hightなど
* 余白関連：padding、layout_margin〇〇系など
* 配置関連：layout_gravity、layout_weightなど
* 文言関連：text、textSize、textStyleなど

以下の記事が参考になります。
* [https://qiita.com/naoi/items/8fb5e565342c3d642411](https://qiita.com/naoi/items/8fb5e565342c3d642411)
* [https://qiita.com/Tsubasa12/items/db7db2fdda3124e3c583](https://qiita.com/Tsubasa12/items/db7db2fdda3124e3c583)
* [https://androidkoko.com/android/gravity.html](https://androidkoko.com/android/gravity.html)

## 実装
[前回の記事](https://qiita.com/hukusima65/items/8d3e131a11215091adac)で調べたように、resフォルダ内のlayoutフォルダ内に画面用XMLを作成します。 <br>

### タイトル画面
縦画面
![スクリーンショット 2024-09-26 003147.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3890153/03d45b62-bdd9-98b2-75e7-c2c25a0a843d.png)


横画面
![スクリーンショット 2024-09-26 003201.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3890153/e6c2a651-3426-d627-253a-1ce9c55397c2.png)

コード
```app/res/layout/activity_title.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:padding="16dp">

    <!-- タイトルテキスト -->
    <TextView
        android:id="@+id/titleText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/app_title"
        android:textSize="32sp"
        android:textStyle="bold"
        android:layout_marginBottom="24dp"
        android:gravity="center" />

    <!-- スタートボタン -->
    <Button
        android:id="@+id/startButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/start_button" />
</LinearLayout>
```

### クイズ画面
縦画面のコードだけでは、横画面になったときレイアウトが崩れてしまったので、横画面用のxmlファイルを作成しました。layoutフォルダと同じ階層にlayout-landフォルダを作成し、同じ名前のxmlフォルダを作成することで、それが横画面用のレイアウトコードになるようです（[こちら](https://qiita.com/QiitaD/items/7d405e93f39a4a3c9d95)を参考）。

縦画面
![スクリーンショット 2024-09-26 003222.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3890153/5e4c357e-c3a7-ddf3-5d21-00cb02b14d35.png)

縦画面のコード
```app/res/layout/activity_quiz.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/flagImage"
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:src="@drawable/sample_flag"
        android:contentDescription="@string/flag_image"
        android:scaleType="centerCrop"
        android:layout_marginBottom="32dp"
        android:layout_marginTop="32dp"/>

    <!-- 国旗を表示する ImageView -->
    <ImageView
        android:id="@+id/flagImage"
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:src="@drawable/sample_flag"
        android:contentDescription="@string/flag_image"
        android:layout_marginBottom="32dp"
        android:layout_marginTop="32dp"/>

    <!-- 4つの選択肢ボタン -->
    <Button
        android:id="@+id/option1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/option1"
        android:layout_marginBottom="16dp"/>

    <Button
        android:id="@+id/option2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/option2"
        android:layout_marginBottom="16dp"/>

    <Button
        android:id="@+id/option3"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/option3"
        android:layout_marginBottom="16dp"/>

    <Button
        android:id="@+id/option4"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/option4"
        android:layout_marginBottom="16dp"/>
</LinearLayout>

```

横画面
![スクリーンショット 2024-09-26 003241.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3890153/7fdaa4fa-46db-03bd-58b1-868af1b6d987.png)

横画面のコード
```app/res/layout-land/activity_quiz.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="16dp">

    <!-- 国旗を表示する ImageView -->
    <ImageView
        android:id="@+id/flagImage"
        android:layout_width="0"
        android:layout_height="200dp"
        android:src="@drawable/sample_flag"
        android:contentDescription="@string/flag_image"
        android:scaleType="centerCrop"
        android:layout_marginStart="16dp"
        android:layout_marginEnd="16dp"
        android:layout_gravity="center_vertical"
        android:layout_weight="1"
        />

    <!-- 選択肢を表示する GridLayout -->
    <GridLayout
        android:layout_width="0dp"
        android:layout_height="200dp"
        android:columnCount="2"
        android:rowCount="2"
        android:layout_gravity="center_vertical"
        android:layout_marginStart="16dp"
        android:layout_weight="1"
        >

        <Button
            android:id="@+id/option1"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_columnWeight="1"
            android:layout_rowWeight="1"
            android:text="@string/option1"
            android:padding="12dp"
            android:layout_margin="8dp" />

        <Button
            android:id="@+id/option2"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_columnWeight="1"
            android:layout_rowWeight="1"
            android:text="@string/option2"
            android:padding="12dp"
            android:layout_margin="8dp" />

        <Button
            android:id="@+id/option3"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_columnWeight="1"
            android:layout_rowWeight="1"
            android:text="@string/option3"
            android:padding="12dp"
            android:layout_margin="8dp" />

        <Button
            android:id="@+id/option4"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_columnWeight="1"
            android:layout_rowWeight="1"
            android:text="@string/option4"
            android:padding="12dp"
            android:layout_margin="8dp" />
    </GridLayout>
</LinearLayout>

```

### 不正解画面
縦画面
![スクリーンショット 2024-09-26 011217.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3890153/2d8cdcf9-5976-ee63-2034-431bb20c80c1.png)

横画面
![スクリーンショット 2024-09-26 011237.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3890153/180d835c-bb34-c2f2-6301-e7d0603225d6.png)

コード
```app/res/layout/activity_incorrect.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:padding="16dp">

    <!-- 残念メッセージ -->
    <TextView
        android:id="@+id/messageTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/game_over"
        android:textSize="24sp"
        android:textStyle="bold"
        android:layout_marginBottom="16dp" />

    <!-- 正解数表示 -->
    <TextView
        android:id="@+id/correctAnswerCountTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/score"
        android:textSize="18sp"
        android:layout_marginBottom="32dp" />

    <!-- タイトルに戻るボタン -->
    <Button
        android:id="@+id/returnToTitleButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/return_title" />
</LinearLayout>

```

### その他
文言の設定
```app/res/values/strings.xml
<resources>
    <string name="app_name">FlagQuizApp</string>
    <string name="app_title">4択国旗クイズ</string>
    <string name="start_button">スタート</string>
    <string name="option1">選択肢1</string>
    <string name="option2">選択肢2</string>
    <string name="option3">選択肢3</string>
    <string name="option4">選択肢4</string>
    <string name="game_over">残念！</string>
    <string name="score">正解数</string>
    <string name="return_title">タイトルへ戻る</string>
</resources>
```

## 終わりに
今回はレイアウトの実装をまとめました。ChatGPTに相談しながら進めましたが、画面案を提示するとコードまで出力してくれたため、そこまで苦労はしませんでした。ただ、横画面にするとレイアウトが崩れたり、余白を調整したりしたい場合は自分でXMLについて調べる必要があり、そこには時間がかかりました。次回、Kotlinによるロジックの実装ができればと思います。

次回は[こちら](https://qiita.com/hukusima65/items/c62957ee74a55912100d)

### 参考
* [https://tech.uzabase.com/entry/2020/04/01/194807](https://tech.uzabase.com/entry/2020/04/01/194807)
* [https://qiita.com/mii-chang/items/ee965c1e8826d4e59414](https://qiita.com/mii-chang/items/ee965c1e8826d4e59414)
* [https://qiita.com/naoi/items/8fb5e565342c3d642411](https://qiita.com/naoi/items/8fb5e565342c3d642411)
* [https://qiita.com/Tsubasa12/items/db7db2fdda3124e3c583](https://qiita.com/Tsubasa12/items/db7db2fdda3124e3c583)
* [https://androidkoko.com/android/gravity.html](https://androidkoko.com/android/gravity.html)
* [https://qiita.com/QiitaD/items/7d405e93f39a4a3c9d95](https://qiita.com/QiitaD/items/7d405e93f39a4a3c9d95)