独学でAndroidアプリを作ってみた
↓誰も遊んでくれないのでダウンロードしてくれると嬉しいな!
https://play.google.com/store/apps/details?id=alpha.app.example.myapplication&pli=1
スマホアプリを作ってみたくてYoutubeやGoogleを漁りながら作ってみました。
子供に邪魔されない時間コツコツと作業したので半年くらいかかっています。
途中どうしても思い通りに動かない!
ということがなんどもあって挫けそうになったり、
デプロイの方法が全くわからずお手上げ状態になりかけましたがなんとかリリースできました。
エンジニア歴2年の時の作品なのでちょっとこれどうなのっていう部分もありますが、
頑張って自分の思い描いたものが形になったときは楽しかったです。
はじめてAndroidアプリ作ってみるという人の参考になればと思い、
どんな構成になっているか説明していきます。
AndroidStudioでの作り方
画面ありきで作っていました。まずlayoutフォルダのxmlファイルで画面、そしてjavaフォルダのKotlinクラスで動きを作っていくというかんじです。
レイアウトにオブジェクト(ボタンなど)を追加して、連携しているKotlinクラスでidから呼び出すことができます。
呼び出したオブジェクトの動きはKotlinファイルで作っていきます。
起動時に実行するアクティビティを指定
AndroidManifest.xml
デフォルトのクラス名と違うので下記マニフェストファイルを修正します。
場所
app/src/main/AndroidManifest.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>
下記で起動時にこのファイルを実行するよ、ということを設定しています。
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
ホーム画面 TitleActivity.kt
このクラスをホーム画面としてます。
このクラスの概要
とりあえず最初の画面なのでクイズのコースを選ぶボタンを配置してます。
画面中央で動いているキャラ等はまた他のクラスにまとめて作っています。
AvatarContainerFragment.kt
として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)と連携するためのクラスになります。
class TitleActivity : AppCompatActivity() {
private lateinit var binding: ActivityTitleBinding
TitleActivityクラスはAppCompatActivityを継承させてアクティビティとして動作するようにしています。
bindingを使ってレイアウトファイルで作成したオブジェクトにアクセスします。
@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でレイアウトのルートビューを取得します。
// 「いちもじ」ボタン
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によって画面遷移が行えるようになります。
レイアウト
res/layout/
ここに画面まわりの設計図があります。
タイトル画面のレイアウトはactivity_title.xmlとして設計してあります。
ここでfragment_avatar_container.xmlというのがlayout属性に入っているのが見えるんですが、
layoutフォルダにあるfragment_avatar_container.xmlをactivity_title.xmlで使っているということです。
さっき作った
AvatarContainerFragment.kt
をfragment_avatar_container.xmlに紐づけて、それぞれのキャラなり、アイテムなり、プログレスバーなりの位置をこのファイルで決めていきます。
fragment_avatar_container.xmlのフラグメント作成
先ほどの画面のパーツfragment_avatar_container.xmlの動きを
AvatarContainerFragment.ktで作っていきます。
import
下記をインポートしています。
Player
SharedViewModel
は自作のクラス。
その他はライラブリからです。
コーディングの中でそれぞれの役割を説明します。
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
として宣言します。
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/