【AndroidStudio,Kotlin】独学で子供向けアルファベットクイズアプリ

# 独学でAndroidアプリを作ってみた
![recode2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/722467/de122420-5b72-f062-a736-3e43a45d92d9.gif)

↓誰も遊んでくれないのでダウンロードしてくれると嬉しいな！
https://play.google.com/store/apps/details?id=alpha.app.example.myapplication&pli=1

スマホアプリを作ってみたくてYoutubeやGoogleを漁りながら作ってみました。
子供に邪魔されない時間コツコツと作業したので半年くらいかかっています。
途中どうしても思い通りに動かない！
ということがなんどもあって挫けそうになったり、
デプロイの方法が全くわからずお手上げ状態になりかけましたがなんとかリリースできました。

エンジニア歴２年の時の作品なのでちょっとこれどうなのっていう部分もありますが、
頑張って自分の思い描いたものが形になったときは楽しかったです。

はじめてAndroidアプリ作ってみるという人の参考になればと思い、
どんな構成になっているか説明していきます。

# AndroidStudioでの作り方
画面ありきで作っていました。まずlayoutフォルダのxmlファイルで画面、そしてjavaフォルダのKotlinクラスで動きを作っていくというかんじです。
レイアウトにオブジェクト（ボタンなど）を追加して、連携しているKotlinクラスでidから呼び出すことができます。
呼び出したオブジェクトの動きはKotlinファイルで作っていきます。


# 起動時に実行するアクティビティを指定
AndroidManifest.xml
デフォルトのクラス名と違うので下記マニフェストファイルを修正します。

場所
app/src/main/AndroidManifest.xml
```xml
        <activity
            android:name=".TitleActivity"
            android:exported="true"
            android:label="@string/app_name"
            android:theme="@style/Theme.MyApplication.NoActionBar">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>

            <meta-data
                android:name="android.app.lib_name"
                android:value="" />
        </activity>
```
下記で起動時にこのファイルを実行するよ、ということを設定しています。
```xml
       <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
```

            

# ホーム画面 TitleActivity.kt
![Screenshot 2024-08-20 at 12.10.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/722467/5268dcd1-7c6d-a947-d3cc-acb765820322.png)

このクラスをホーム画面としてます。

## このクラスの概要
とりあえず最初の画面なのでクイズのコースを選ぶボタンを配置してます。

画面中央で動いているキャラ等はまた他のクラスにまとめて作っています。
AvatarContainerFragment.kt
としてKotlinクラスを作って、キャラクター画像、レベルや持っているアイテム、名前などを表示する枠を作ります。


## ライラブリなど

```kotlin
package alpha.app.example.myapplication

import android.annotation.SuppressLint
import android.content.Intent
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import alpha.app.example.myapplication.databinding.ActivityTitleBinding

```
Intentはアクティビティ間の遷移に使っています。
AppCompatActivityはアクティビティを作成する時のクラスです。
そしてActivityTitleBindingは対応するレイアウトファイル（activity_title.xml）と連携するためのクラスになります。

```kotlin
class TitleActivity : AppCompatActivity() {

    private lateinit var binding: ActivityTitleBinding
```
TitleActivityクラスはAppCompatActivityを継承させてアクティビティとして動作するようにしています。
bindingを使ってレイアウトファイルで作成したオブジェクトにアクセスします。

```kotlin
    @SuppressLint("DiscouragedApi")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding = ActivityTitleBinding.inflate(layoutInflater)
        val view = binding.root
        setContentView(view)
```
onCreateでアクティビティを呼び出しています。
ActivityTitleBinding.inflate(layoutInflater)で、レイアウトを呼び出しています。
binding.rootでレイアウトのルートビューを取得します。

```kotlin
        // 「いちもじ」ボタン
        binding.buttonOneAlphabet.setOnClickListener {
            startActivity(Intent(this@TitleActivity, AlphabetQuizActivity::class.java))
        }

        // 「たんご」ボタン
        binding.buttonWord.setOnClickListener {
            startActivity(Intent(this@TitleActivity, WordQuizActivity::class.java))
        }

        // 「あたらしくはじめる」ボタン
        binding.buttonNewGame.setOnClickListener {
            startActivity(Intent(this@TitleActivity, InputNameActivity::class.java))
        }
    }
}
```
Intentによって画面遷移が行えるようになります。


## レイアウト
![Screenshot 2024-08-20 at 12.16.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/722467/0e333895-6194-3311-72f1-bde6ba541e74.png)

res/layout/
ここに画面まわりの設計図があります。
タイトル画面のレイアウトはactivity_title.xmlとして設計してあります。
![Screenshot 2024-08-20 at 12.19.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/722467/64a4ec0a-ab14-e4af-77b6-e0df0207f8d6.png)


ここでfragment_avatar_container.xmlというのがlayout属性に入っているのが見えるんですが、
layoutフォルダにあるfragment_avatar_container.xmlをactivity_title.xmlで使っているということです。

![gamen.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/722467/8b694141-6d2b-4116-2116-10cb8f97b6b8.png)


さっき作った
AvatarContainerFragment.kt
をfragment_avatar_container.xmlに紐づけて、それぞれのキャラなり、アイテムなり、プログレスバーなりの位置をこのファイルで決めていきます。
![Screenshot 2024-08-20 at 12.27.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/722467/609aecc0-bb73-8535-f796-f0454b9c5854.png)

## fragment_avatar_container.xmlのフラグメント作成
先ほどの画面のパーツfragment_avatar_container.xmlの動きを
AvatarContainerFragment.ktで作っていきます。

### import
下記をインポートしています。
Player
SharedViewModel
は自作のクラス。

その他はライラブリからです。
コーディングの中でそれぞれの役割を説明します。

```kotlin
import Player
import SharedViewModel
import android.annotation.SuppressLint
import android.content.Context
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.animation.AnimationUtils
import android.widget.ImageView
import android.widget.ProgressBar
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import alpha.app.example.myapplication.databinding.FragmentAvatarContainerBinding

```

### パブリック変数などの宣言など

ARG_PARAM1はレベルアップしたかどうか、
ARG_PARAM2はクイズで取得しているポイント数を表しています。
画面遷移の際に渡す変数なのでここで宣言しておきます。

このクラスは画面の一部に使うフラグメントクラスなので
Fragment()
を継承しています。

プレイヤーそれぞれの情報を持ったPlayerクラス
画面と紐づいているFragmentAvatarContainerBinding
状態管理のクラスであるSharedViewModelを

player
binding
viewModel

として宣言します。

```kotlin
private const val ARG_PARAM1 = "booleanLevelUp"
private const val ARG_PARAM2 = "points"

class AvatarContainerFragment : Fragment() {

    private lateinit var player: Player
    private lateinit var binding: FragmentAvatarContainerBinding
    private lateinit var viewModel: SharedViewModel

    private var param1: Boolean = false
    private var param2: Int = 0

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        arguments?.let {
            param1 = it.getBoolean(ARG_PARAM1)
            param2 = it.getInt(ARG_PARAM2)
        }
    }

```

つづく

# Gitリポジトリ、使用素材など

Alphabetquiz2 - このアプリのリポジトリ、自由に改変可
https://github.com/otaruit/AlphabetQuiz2.git

DOT ILLUST - かわいいドット絵素材
https://dot-illust.net/character_cook_black/

あみたろの声素材工房　- 音声素材など
https://amitaro.net/voice/voice_rule/