[Android]Kotlinで簡単な画面遷移

先日よりプログラミングの学習を始めました。Kotlinでボタンをタップして画面遷移を行う簡単な画面遷移アプリを作成したので、一通りの手順を書き起こします。

**実行環境**
AndroidStudio3.4

#Activityを作成
まず始めに起動時画面となるMainActivityと、遷移後に表示する画面であるSubActivityを作成します。

※既にプロジェクトを開いている前提になります。
※プロジェクトを新規作成した直後の場合はMainActivityはデフォルトで作成されます。SubActivity作成の手順からスタートしてください。

AndroidStudioの上部メニューから
[File]→[New]→[Activity]→[EmptyActivity] を選択し、表示されるダイアログ内の以下の項目をそれぞれ以下の内容に変更してください。

・Activity Name: MainActivity
・Generate Layout Fileにチェックを入れる。
・Layout Name : activity_main
・Launcher Activityのチェックは外す。
・Package nameはデフォルト値でOK。
・Source LanguagesはKotlinを選択。

上記の変更を加えたらFinishでMainActivityが作成されます。

SubActivityも同様の手順を踏んで作成します。上記の内容のうちActivity NameとLayuout Nameの部分を以下のように変更し、それ以外はMainActivity作成時と同じ内容で作成します。

Activity Name: SubActivity
Layout Name: activity_sub

以上で必要なAcitivityの作成は終了です。

#レイアウトを作成

次にActivity作成時に同時生成されたレイアウトファイルにそれぞれ変更を加えていきます。
activity_mainファイルには画面遷移用のボタンを配置、SubActivityには画面遷移が行われた事が分かりやすいようにTextViewに変更を加えます。

以下コードです。

```activity_main.xml
<LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    <Button
            android:id="@+id/btn_intent"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="画面遷移！"/>

</LinearLayout>

```

```activity_sub.xml
<LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    <TextView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:gravity="center"
            android:text="画面遷移完了！"/>

</LinearLayout>
```

以上でレイアウトの作成も終了です。残りは実際の処理になります。

※ここではサンプルとしてレイアウトのandroid:text属性の文字列指定で直接文字列を記入していますが、実際の開発ではリソースファイルに文字列を定義してその値を指定するようにしてください。

#画面遷移処理の記述

いよいよ画面遷移処理の記述をしていきます。
まず最初にMainActivity内のコードを以下のように変更します。
SubActivityは作成時のままで大丈夫です。

```MainActivity.kt
import android.content.Intent
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.widget.Button

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        //1.画面遷移用ボタンの取得。
        val btnIntent = findViewById<Button>(R.id.btn_intent)
        //2.画面遷移用ボタンにリスナを登録。
        btnIntent.setOnClickListener (object : View.OnClickListener {
            override fun onClick(v: View?) {
                //3.Intentクラスのオブジェクトを生成。
                val intent = Intent(this@MainActivity, SubActivity::class.java)
                //生成したオブジェクトを引数に画面を起動！
                startActivity(intent)
            }
        })
    }
}
```

上記のコードで画面遷移の実装は完了です。
今回実装したい画面タップ時に画面遷移を行うという処理で重要なのは、上記コードの2と3,4です。
2ではボタンタップ時に特定の処理を行わせるためにイベントリスナというものをボタンに設定しています。
3,4でIntentクラスのオブジェクトを利用してstartActivityメソッドでSubActivityを起動し画面遷移処理を開始しています。
それぞれについて解説します。

#イベントリスナ

UI上の部品（ここではMainActivity上のボタンを指します）は、レイアウト上に置いただけではアプリ起動後にタップしても何の処理も行われません。
なので、タップを検出した際に処理を行う役目を担っているView.OnClickListenerインターフェース(以下、OnClickListener)を実装し、それをsetOnClickListenerメソッドでボタンに設定します。

**OnClickListener**
Androidでは一般に、画面タップ等のユーザーが画面に対して行う操作を**イベント**、そのイベントに対応して行う処理の事を**イベントハンドラ**、イベントの検出を行っているものを**リスナ**と呼称します。
そして、OnClickListenerインターフェースはAndroidデバイスの画面に存在するUI部品のタップが検知された際に、その部品に対しOnClickListenerが実装されていた場合にその検出時の処理を引き継ぐ役目を担っています。つまり、UIタップ時の**イベント**を検出する**リスナ**の役割を持っています。
残るは実際に処理を行う役割を持つ**イベントハンドラ**ですが、それはOnClickListenerインターフェースが持つメソッドが担います。
OnClickListenerインターフェースはonClickという抽象メソッドを一つだけ持ち、ここにタップ検出時に行いたい実際の処理を記述します。

今回はタップ時に画面遷移を行いたいので、サンプルではOnClickListenerを実装した匿名クラスを作成、およびonClickメソッドをオーバーライドして、onClickメソッド内に画面遷移処理を記述しています。


#IntentとstartActivity()

前項でボタンタップ時処理を実装する前段階までの準備が整いました。
あとはオーバーライドしたonClickメソッド内で画面遷移処理を記述すれば完成です。

画面遷移を実現する上で使用するクラスがIntentクラスとstartActivityメソッドです。

Intentとはとてつもなく簡潔に述べるなら、異なるActivity、異なるアプリケーション間の橋渡しをしてくれる存在です。自身のアプリケーション内で別のActivityを起動する時も、外部のアプリケーションを起動する時にも使用される、幅広い用途で活躍する便利屋さんですね。
そのIntentクラスを今回は別画面のActivityを起動する為に利用します。

startActivityメソッドはIntentオブジェクトの情報を元に実際にActivityを起動するメソッドです。

```MainActivity.kt
//3.Intentクラスのオブジェクトを生成。
val intent = Intent(this@MainActivity, SubActivity::class.java)
//生成したオブジェクトを引数に画面を起動！
startActivity(intent)
```

Intentオブジェクトの作成時に必要な引数は2つです。

*第1引数 packageContext Context* 
コンテキストです。
ここではMainActivityのコンテキストをそのまま渡しています。

*第2引数 cls Class<?>*
起動先となるActivityのクラス情報です。
ここではSubActivityのクラス情報をJavaクラス化したものを渡しています。

☆補足：「SubActivity::class.java」の「::class.java」って何？？となる方に。
Kotlinではclassを表す書き方として「クラス名::class」という書き方を用います。
そこからさらにIntentオブジェクト生成の第2引数にはjavaクラスを渡す必要があるので、「.java」を末尾に記述することによってKotlinクラスをjavaクラス扱いとして渡しています。

startActivityメソッドの起動に必要なのは起動したいActivityの情報が込められたIntentオブジェクトです。

以上で画面遷移アプリの作成は完了です。

#まとめ

最後に、今回実装した画面遷移処理の流れを一度おさらいしましょう。

1.遷移元となるActivityと遷移先となるActivityをそれぞれ用意。
2.それぞれのActivityのレイアウトを用意。
3.トリガーとしたいUIにリスナ(今回はOnClickListenerインターフェース)をセット。
4.リスナを実装したクラスを作成（今回は匿名クラスを作成）。
5.クラス内でイベントハンドラ(今回はonClickメソッド)をオーバーライド。
6.イベントハンドラ内で画面遷移処理を記述する。

上記の手順を踏んで画面遷移を実装しています。
画面遷移といってもボタンタップで遷移する場合以外にも遷移を行いたいという場合もありますし、細かい部分まで暗記するよりは、おおまかな流れだけ覚えておいて、その流れに沿いながら細かい部分は適宜実際に実装したい機能に合わせて変えていくのが良いのではないかと思います。

以上です。


#おまけ

今回の画面遷移処理において、リスナクラスを作成する際に匿名クラスというものが出てきましたが、正直匿名クラスというものが何なのかよく分からない…という方も多いと思います。
匿名クラスについて記述すると長くなってしまいますので、今回はそちらの詳しい情報は他の方にお譲りするとして…（後日自分自身の深い理解の為に記事にしたいとは思います。）

匿名クラスとして宣言するうんぬんの前に、普通のクラスとして宣言をした場合はどういった形になるのか？というのをあらかじめ知っておくと、匿名クラスについての理解も早くなるのではないかと思うので、そちらの例を記載しておきます。

例にしますと、今回の実装では下記のようになっていた記述が…

```MainActivity.kt
 //画面遷移用ボタンの取得。
 val btnIntent = findViewById<Button>(R.id.btn_intent)
 //画面遷移用ボタンにリスナを登録。
 btnIntent.setOnClickListener (object : View.OnClickListener {
     override fun onClick(v: View?) {
         //3.Intentクラスのオブジェクトを生成。
         val intent = Intent(this@MainActivity, SubActivity::class.java)
         //生成したオブジェクトを引数に画面を起動！
         startActivity(intent)
     }
```

こういった形になります。

```MainActivity.kt

 //1.画面遷移用ボタンの取得。
 val btnIntent = findViewById<Button>(R.id.btn_intent)
 //2.画面遷移用ボタンにリスナを登録。
 btnIntent.setOnClickListener (btnClickListener())
}

private inner class btnClickListener : View.OnClickListener{
        override fun onClick(v: View?) {
            //3.Intentクラスのオブジェクトを生成。
            val intent = Intent(this@MainActivity, SubActivity::class.java)
            //生成したオブジェクトを引数に画面を起動！
            startActivity(intent)
        }
    }
```

btnClickListenerクラスが新しく定義されています。端的に言ってしまえば、本文で匿名クラスとして宣言していたリスナクラスに名前を与えてキチンと定義をしたものがこちらのbtnClickListenerクラスです。
こちらのクラスも匿名クラスと同じようにView.OnClickListenerインターフェースを実装しています。
匿名クラスで宣言していた時と同じようにonClickメソッドをオーバーライドして、実際に処理したい内容を記述していますね。
そして、btnIntentのsetOnClickListener()でbtnClickListenerを指定しています。

匿名クラスという名前と実際の扱い方をぱっと見るとなんだかとても複雑そうに見えますが、匿名クラスはあくまで省略形の記述方法です。つまり、省略する前の完全な形をあまり理解していない状態で取り掛かっても上手く飲み込めない事も多いと思います（私も最初そうでした。もしかして私だけ…？）。
ですが、こうやって元々の形に直せば匿名クラスで何がしたかったのかも段々と理解出来るようになると思います。
匿名クラスについての詳しい事は先述の通り先駆者様にお譲り致しますが、そちらを学習していく上での足掛かりになれたら幸いと思います。


#おわりに

拙い文章でしたが、もし間違っている点等あれば指摘を頂けるとありがたいです。
ありがとうございました。