Android Kotlin基礎講座 01.2: 基本的なアプリの構造
目次
タスク:ボタンを追加する
サイコロを振るアプリはユーザーがサイコロを振り、その結果が見えるようでなければ有用とは言えません。はじめにサイコロを振るためのボタンをレイアウトに追加し、その後に振った結果を表示するテキストを追加していきます。
ステップ1:レイアウトにボタンを追加する
- テキストビューの下にボタン要素を追加します。XMLで<TextView>要素の下に<Buttonと入力してエンターキーを押してください。/>が最後に表示されボタンブロックが出来上がります。また中にlayout_widthとlayout_height属性を含んでいます。
<Button
android:layout_width=""
android:layout_height="" />
- layout_widthとlayout_height属性の値を両方とも”wrap_content”にしてください。この値によってボタンの高さと幅が表示するテキストの高さと幅と同じになります。
- android:text属性をボタンに追加してください。値は”Roll”にしてください。ここまでのボタン要素は以下のようになります。
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Roll" />
ボタンビューにとってtext属性はボタンのラベルです。レイアウトエディターでtext属性が黄色くハイライトされていると思います。これはヒント、または警告を意味しています。今回の場合はRollという文字がハードコード(変更不可)として扱われているためです。Android Studioでは文字は基本的にstringリソースとして扱うことを推奨しています。stringリソースについて次のステップで学習しましょう。
ステップ2:stringリソースの抽出
開発中のアプリのレイアウトまたはコードファイル中のハードコードのstringの代わりに、すべてのstringを別のファイルに抽出しましょう。別のファイルとはstrings.xmlのことです。このファイルはres/valuesディレクトリーに存在します。
stringをリソースとして別のファイルの保存しておくことでそれらを変更したり、複数回同じstringを利用したい時など、管理するのが容易になります。またstringリソースは各国の言語に翻訳してローカライズするためには必須です。なぜならローカライズのたえにはそれぞれの言語用のstringリソースを作る必要があるからです。
Android Studioはハードコードのstringをstringリソースに置き換えることをヒントや警告を用いて手助けしてくれます。
- <Button>タグの中のandroid:text属性のRollというstringの上で一度クリックしてください。
- Alt+Enter(macの場合Option+Enter)を押して、ポップアップメニューからExtract string resourceをを選択してください。
- Resource nameにはroll_labelと入力してください。
- OKをクリックしてください。これでres/values/strings.xmlにstringリソースが作成され、Button要素のstringがstringリソースを参照するための値に置き換えられました。
- Project>Androidからres>valuesを展開し、strings.xmlをダブルクリックで開いてstringリソースを確認してみてください。
<resources>
<string name="app_name">DiceRoller</string>
<string name="roll_label">Roll</string>
</resources>
Tip: 今追加したstringに加えて、strings.xmlファイルにはアプリの名前も含まれています。アプリの名前はEmptyテンプレートを利用しているアプリを起動した際にアプリバーとして画面上部に表示されます。アプリの名前はこのapp_nameリソースを編集することによって変更することができます。
ステップ:スタイルと位置
あなたのレイアウトは現在テキストビューとボタンビューをひとつずつ含んでいます。このステップではアプリをより魅力的に見せるためにビューグループのビューをアレンジしていきます。
- レイアウトのプレビューを見るためにDesignタブをクリックしてください。現在は二つのビューが隣り合い、画面の上部に押し上げられたように表示されています。
- TextタブをクリックしてXMLエディターに戻ってください。android:orientation属性をLinearLayoutタグの中に追加してください。値は”vertical”としてください。<LinearLayout>要素は以下のようになります。
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
tools:context=".MainActivity">
LinearLayoutビューグループは子として含んでいるビューを順番に一列(水平方向に一列、または垂直方向に一列)に配置します。デフォルトでは水平方向に配置されます。今回はテキストビューをボタンの上に配置したいので、orientation(方向)をvertical(垂直)にします。
ここまでのデザインは以下のようになります。
- 次にandroid:layout_gravity属性をTextViewとButtonの両方に追加してください。値は両方とも”center_horizontal”に設定してください。これによって二つのビューを水平線上の中心に整列させます。ここまでのTextViewとButtonのコードは以下のようになります。
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="Hello World!" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="@string/roll_label" />
- android:layout_gravity属性をlinear layoutにも追加してください。値は”center_vertical”としてください。コードは以下のようになります。
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_gravity="center_vertical"
tools:context=".MainActivity">
Note: ボタンとテキストビューのlayout_gravityの値を”center_vertical”にした場合、二つのビューは縦向きにも横向きにもレイアウトの中心に位置するようになります。つまり、二つのビューはお互いのトップに位置します。
一度にすべての子要素を中心に寄せるためには、上で行ったように、親要素(ここではLinearLayout)にcenter_verticalを適用してください。
- テキストビューの文字サイズを大きくするために、<TextView>要素にandroid:textSize属性を追加して、値を”30sp”に設定してください。spとはscalable pixels(拡張可能な画素)の略で、端末の解像度に依存しない文字サイズの単位です。TextView要素は以下のようになります。
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:textSize="30sp"
android:text="Hello World!" />
- コンパイルしてアプリを起動してみてください。
これでテキストとボタンがきれいに整列され、文字も見やすくなりました。
ボタンは今のところ何の機能も実装していないので、押しても何も起こりません。次のステップでボタンに機能を実装していきます。
ステップ4:コードからボタンの参照を得る
MainActivityのKotlinコードは、ボタンをタップしたときに何が起こるようにするかなど、アプリの相互作用性を定義する場所でもあります。ボタンがタップされたときに実行される機能を書いていくために、まずはMainActivityのインフレートされたレイアウトの中のボタンというオブジェクトの参照を得なければなりません。以下の手順でボタンの参照を得ることができます。
- XMLファイルでボタンにIDを指定する。
- IDを利用してビュー(ボタン)の参照を得るために、コード上でfindViewById()メソッドを利用する。
一度ボタンの参照を得てしまえば、アプリ起動後にボタン上のメソッドを動的に呼び出すことができます。例えば、ボタンがタップされたときにあるコードを実行するクリックハンドラーを追加することができます。
- まだ開いていなければactivity_main.xmlレイアウトファイルを開いてください。Textタブをクリックしてコードを表示してください。
- ボタンにandroid:id属性を追加してください。名前を追加します。(今回は”@+id/roll_button”) <Button>要素は以下のようになります。
<Button
android:id="@+id/roll_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="@string/roll_label" />
レイアウトファイルからビューのIDを作成するとAndroid StudioはRクラスの中のID名に紐づくinteger定数を生成します。つまりビューにroll_buttonと命名した場合、Android StudioはRクラスの中にroll_buttonという名前のinteger定数を生成します。”@+id”というID名の接頭辞はコンパイラーに対して、RクラスにそのIDの定数を追加するように伝える役割を果たしています。すべてのXMLファイル中のIDは必ずこの接頭辞を持っていなければなりません。
- MainActivity Kotlinファイルを開いてください。onCreate()の中のsetContentView()のあとに次のコードを追加してください。
val rollButton: Button = findViewById(R.id.roll_button)
XMLファイルで定義したビューの参照を得るためにfindViewById()メソッドを利用します。今回の場合は、Rクラスからroll_buttonというIDを使ってボタンの参照を得ています。そうして取得した参照をrollButtonという変数に保存しています。
Note: もしコピー&ペーストせずにコードを入力した場合、IDを入力しはじめた際にAndroid StudioがIDの自動入力候補を表示してくれます。
- Android StudioがButtonクラスを赤色にハイライトし下線を引いているのを確認してください。これは参照が有効ではないということと、Buttonクラスを利用する前に、Buttonクラスをimportしなければならないということを示しています。Android Studioが最適なクラス名を表示してくれていると思います。
Alt+Enter(Macの場合Option+Enter)を押して、ヒントに表示されているクラス名を承認してください。
Tip: コードの意味が曖昧でない場合に、Android Studioが自動で適切なインポート文を記述してくれるように設定することができます。Editor>General>Auto Importからimportの設定を行うことができます。
ステップ5:トーストを表示するためのクリックハンドラーを追加する
クリックハンドラーとはユーザーがボタンのようなクリック(スマホの場合タップのこと)可能なUI要素をクリックする度に呼び出されるメソッドのことです。クリックハンドラーを作るためには以下が必要です。
- 何らかの処理を行うメソッド
- ボタンとハンドラーメソッドを繋ぐためのsetOnClickListener()メソッド
このステップではトースト(画面下部に短時間表示されるポップアップメッセージ)を表示するクリックハンドラーメソッドを作成していきます。そのハンドラーメソッドをボタンに紐づけます。
- MainActivityの中のonCreate()のあとに、rollDice()という名前のプライベート(同じクラスからのみ呼び出し可能)な機能を作成してください。
rivate fun rollDice() {
}
- rollDice()メソッドにトーストを表示するためのコードを追加します。
Toast.makeText(this, "button clicked",
Toast.LENGTH_SHORT).show()
トーストを作成するためにはToast.makeText()メソッドを呼び出します。このメソッドは以下の三つの引数を必要とします。
- Contextオブジェクト。ContextオブジェクトはAndroid OSとやり取りをし、現在の状態についての情報を得るためのクラスです。ここではToastオブジェクトがOSに対してトーストを表示するように伝えられるようにするために、Contextオブジェクトが必要です。実はAppCompatActivityはContextクラスのサブクラスなので、ここではthisと指定するだけで大丈夫です。
- 表示するメッセージ。ここでは”button clicked”と指定しています。
- メッセージを表示する時間。ここではToastクラスの定数を指定しています。最後のshow()メソッドでトーストを表示しています。
- onCreate()の中のfindViewById()の後に次のコードを追加してください。これによってrollDice()メソッドをrollButtonオブジェクトのクリックハンドラーとして設定しています。
rollButton.setOnClickListener { rollDice() }
最終的なMainActivityファイルは以下のようになります。
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val rollButton: Button = findViewById(R.id.roll_button)
rollButton.setOnClickListener { rollDice() }
}
private fun rollDice() {
Toast.makeText(this, "button clicked",
Toast.LENGTH_SHORT).show()
}
}
- コンパイルしてアプリを起動してください。ボタンをタップする度にトーストが表示されます。