[Kotlin] Androidの画面遷移とアクティビティ間の値の受渡し

By | 2018年1月24日

Androidアプリにおける基本的な画面遷移の方法についてです。画面遷移とは、あるアクティビティ(Activityクラス)のから別のアクティビティを開くことです。

実際に画面遷移を行うサンプルアプリを作ることを通して、前のアクティビティから値を引き継いで新しく開いたアクティビティで使う方法と、逆に新しく開いたアクティビティを閉じた際に元のアクティビティで値(処理結果など)を受け取る方法について紹介します。

サンプルはAPIレベル15以上で動作します。

サンプルアプリの動作

アプリを起動すると、テンプレートにボタンがひとつだけ追加された画面が表示されます。

画面遷移を行うAndroidアプリを起動した画面

このボタンを押すと、次の画面(SecondActivity)を開きます。

この際に、プログラムで設定した値(例では整数「120」と文字列「The message from MainActivity」)を次のアクティビティに渡します。

SecondActivity は、そのアクティビティを閉じて元のアクティビティに戻るためのボタンだけを持つ画面です。また、その画面を開いたとき Toast で受け取った値を表示します。

startActivityForResultで新しくアクティビティを開いて同時に値を渡す

閉じるボタンを押すと、元の画面に戻ります。この時 SecondActivity で設定した値(例では整数「300」と文字列「The message from SecondActivity」)を受け取って Toast で表示します。

元のアクティビティに戻った時、前のアクティビティから情報を受け取って表示

サンプルアプリのXMLとプログラム

上記のサンプルを構成するXMLレイアウトとプログラム(Kotlin)についてです。

合計4つのファイルを使用しています。

また、マニフェスト(AndroidManifest.xml)の追記も必要になります。

MainActivity

最初のアクティビティのレイアウトとプログラムです。

activity_main.xml

デフォルトのレイアウトにボタン(idはbutton1)をひとつ追加しているだけです。

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="activity.example.com.newactivitytest.MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Open SecondActivity" />

</android.support.constraint.ConstraintLayout>

MainActivity.kt

MainActivity を構成する Kotlin のプログラムです。

package activity.example.com.newactivitytest

import android.app.Activity
import android.content.Intent
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.Toast

const val MY_REQUEST_CODE = 0

class MainActivity : AppCompatActivity() {

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

        val button: Button = findViewById(R.id.button1)
        button.setOnClickListener {

            // 新しく開くアクティビティに渡す値
            val intent: Intent = Intent(this, SecondActivity::class.java)
            intent.putExtra("number", 120)
            intent.putExtra("string", "The message from MainActivity")

            // 新しくアクティビティを開く
            startActivityForResult(intent, MY_REQUEST_CODE)
        }
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {

        if (requestCode == MY_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
            // リクエストコードが一致してかつアクティビティが正常に終了していた場合、受け取った値を表示
            val received = data!!
            Toast.makeText(this, "${received.extras.get("number")}, ${received.extras.get("string")}", Toast.LENGTH_LONG).show()
        }
    }
}

2つ目のアクティビティに遷移する処理は以下の部分です。

// 新しく開くアクティビティに渡す値
val intent: Intent = Intent(this, SecondActivity::class.java)
intent.putExtra("number", 120)
intent.putExtra("string", "The message from MainActivity")

// 新しくアクティビティを開く
startActivityForResult(intent, MY_REQUEST_CODE)

別の画面のアクティビティは、クラス Intent を利用して起動します。

以下のように、第二引数に起動する対象のアクティビティのクラスを指定します。

val intent: Intent = Intent(this, SecondActivity::class.java)

起動したアクティビティに渡す値はメソッド putExtra で設定します。数値や文字列、リストなどを指定可能です。今回は整数と文字列を渡しています。

intent.putExtra("number", 120)
intent.putExtra("string", "The message from MainActivity")

このように設定した Intent から、実際にアクティビティを起動するには startActivityForResult を使用します。

startActivityForResult(intent, MY_REQUEST_CODE)

MY_REQUEST_CODE は、後で情報を受け取る際に「どこで起動したアクティビティか」を調べる際に使用する任意の整数値です。サンプルでは定数として定義しています。値は整数値であればなんでも構いません。

startActivity というメソッドも存在しますが、こちらは開いたアクティビティから情報を受け取らない場合に使用します。今回は SecondActivity を閉じた際に情報を受け取るので startActivityForResult を使用して下さい。

onActivityResult は SecondActivity を閉じた際に情報を受け取るためのメソッドです。変数 data には、返された値が格納されています。

SecondActivity

MainActivityから起動される2つ目の画面のレイアウトとプログラムです。

activity_second.xml

ボタンをひとつだけ表示するレイアウトです。ボタンの id は button2 としています。

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Close SecondActivity" />

</android.support.constraint.ConstraintLayout>

SecondActivity.kt

SecondActivity の Kotlin のプログラムです。ファイルを分けていますが MainActivity.kt の中に書いても問題ありません。

package activity.example.com.newactivitytest

import android.app.Activity
import android.content.Intent
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.widget.Button
import android.widget.Toast

class SecondActivity : AppCompatActivity() {

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

        // MainActivity から渡された値を表示
        Toast.makeText(this, "${intent.extras.get("number")}, ${intent.extras.get("string")}", Toast.LENGTH_LONG).show()

        val button: Button = findViewById(R.id.button2)
        button.setOnClickListener {

            // 渡す値を設定
            val intent = Intent()
            intent.putExtra("number", 300)
            intent.putExtra("string", "The message from SecondActivity")

            // 情報を渡して MainActivity の onActivityResult を呼び出す
            setResult(Activity.RESULT_OK, intent)

            // アクティビティを閉じる
            finish()
        }
    }
}

前のアクティビティから渡された情報は以下の変数に格納されています。

intent.extras

先程 MainActivity で設定した値は、以下のように取り出すことができます。

intent.extras.get("number")
intent.extras.get("string")

このアクティビティを閉じると、以下のように設定した情報が元のアクティビティに返されます。実際のアプリでは、処理の結果などをこのように設定して元のアクティビティに渡します。

val intent = Intent()
intent.putExtra("number", 300)
intent.putExtra("string", "The message from SecondActivity")

setResult(Activity.RESULT_OK, intent)

setResult は、元のアクティビティで定義した onActivityResult を呼び出します。

アクティビティを閉じるには finish を実行します。これで、アクティビティを閉じて元のアクティビティに戻ると同時に、その onActivityResult を呼び出すことができます。

AndroidManifest.xml

新しいアクティビティを追加した際には、そのアクティビティを必ずマニフェスト(AndroidManifest.xml)に追記します。これを行わないと、新しいアクティビティを起動させようとした場合、アプリがクラッシュします。

以下のように、applicationタグ内にactivityタグを追加して下さい。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="activity.example.com.newactivitytest">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

        <activity android:name=".SecondActivity"></activity>
    </application>

</manifest>

おしまい

以上がAndroidアプリにおける画面遷移と、遷移時に値を受け渡す方法です。

これを応用することで、複数の画面で情報を共有するアプリを作成することができます。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です