[Android/Kotlin]画面遷移時にActivityに値を渡す

目次

概要

ソースコード

.ktファイル

MainActivity.kt
package com.seeking_star.test

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.seeking_star.test.ui.main.MainFragment

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        if (savedInstanceState == null) {
            supportFragmentManager.beginTransaction()
                .replace(R.id.container, MainFragment.newInstance())
                .commitNow()
        }
    }
}
Kotlin
Kotlin
package com.seeking_star.test.ui.main

import android.content.Intent
import androidx.lifecycle.ViewModelProvider
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.RadioGroup
import com.seeking_star.test.Enumration.MagicType
import com.seeking_star.test.R
import com.seeking_star.test.SubActivity

class MainFragment : Fragment() {

    companion object {
        fun newInstance() = MainFragment()

        val MAGIC_TYPE = "com.seeking_star.test.MainFragment.MagicType"
    }

    private lateinit var viewModel: MainViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        viewModel = ViewModelProvider(this).get(MainViewModel::class.java)
        // TODO: Use the ViewModel
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        var view = inflater.inflate(R.layout.fragment_main, container, false)
        var radioGroup = view.findViewById<RadioGroup>(R.id.magicTypeGroup)

        view.findViewById<Button>(R.id.decideButton).setOnClickListener {
            // ラジオボタンの選択状態を取得する
            var selectedType = when (radioGroup.checkedRadioButtonId) {
                R.id.radioFire -> MagicType.FIRE
                R.id.radioIce -> MagicType.ICE
                R.id.radioWind -> MagicType.WIND
                R.id.radioElectric -> MagicType.ELECTRIC
                R.id.radioBomb -> MagicType.BOMB
                R.id.radioDark -> MagicType.DARK
                else -> null
            }

            if (selectedType != null) {
                var intent = Intent(context, SubActivity::class.java)
                intent.putExtra(MAGIC_TYPE, selectedType)
                startActivity(intent)
            }
        }

        return view
    }
}
Kotlin
SubActivity.kt
package com.seeking_star.test

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.seeking_star.test.Enumration.MagicType
import com.seeking_star.test.ui.main.MainFragment
import com.seeking_star.test.ui.main.SubFragment

class SubActivity : AppCompatActivity() {

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

        // 受け取った値をMagicTypeにして受け取る
        var magicType = intent.getSerializableExtra(MainFragment.MAGIC_TYPE) as MagicType
        var title = when (magicType) {
            MagicType.FIRE -> "メラ属性"
            MagicType.ICE -> "ヒャド属性"
            MagicType.WIND -> "バギ属性"
            MagicType.ELECTRIC -> "デイン属性"
            MagicType.BOMB -> "イオ属性"
            MagicType.DARK -> "ドルマ属性"
        }

        supportActionBar?.setDisplayHomeAsUpEnabled(false)
        supportActionBar?.title = title

        if (savedInstanceState == null) {
            supportFragmentManager.beginTransaction()
                .replace(R.id.container, SubFragment.newInstance(magicType))
                .commitNow()
        }
    }
}
Kotlin
SubFragment.kt
package com.seeking_star.test.ui.main

import androidx.lifecycle.ViewModelProvider
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import com.seeking_star.test.Enumration.MagicType
import com.seeking_star.test.R

class SubFragment : Fragment() {

    companion object {
        fun newInstance() = SubFragment()

        // メンバ変数に値を代入してインスタンス化する
        @JvmStatic
        fun newInstance(magicType: MagicType) =
            SubFragment().apply {
                arguments = Bundle().apply {
                    putSerializable(MainFragment.MAGIC_TYPE, magicType)
                }
            }
    }

    private lateinit var viewModel: MainViewModel
    private lateinit var magicType: MagicType

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        viewModel = ViewModelProvider(this).get(MainViewModel::class.java)
        // ここで値をセットする
        arguments?.let {
            magicType = it.getSerializable(MainFragment.MAGIC_TYPE) as MagicType
        }
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        val view = inflater.inflate(R.layout.fragment_sub, container, false)

        when (magicType) {
            MagicType.FIRE -> {
                view.findViewById<TextView>(R.id.textlevel1).setText("メラ")
                view.findViewById<TextView>(R.id.textlevel2).setText("メラミ")
                view.findViewById<TextView>(R.id.textlevel3).setText("メラゾーマ")
            }
            MagicType.ICE -> {
                view.findViewById<TextView>(R.id.textlevel1).setText("ヒャド")
                view.findViewById<TextView>(R.id.textlevel2).setText("ヒャダルコ")
                view.findViewById<TextView>(R.id.textlevel3).setText("マヒャド")
            }
            MagicType.WIND -> {
                view.findViewById<TextView>(R.id.textlevel1).setText("バギ")
                view.findViewById<TextView>(R.id.textlevel2).setText("バギマ")
                view.findViewById<TextView>(R.id.textlevel3).setText("バギクロス")
            }
            MagicType.ELECTRIC -> {
                view.findViewById<TextView>(R.id.textlevel1).setText("デイン")
                view.findViewById<TextView>(R.id.textlevel2).setText("ライデイン")
                view.findViewById<TextView>(R.id.textlevel3).setText("ギガデイン")
            }
            MagicType.BOMB -> {
                view.findViewById<TextView>(R.id.textlevel1).setText("イオ")
                view.findViewById<TextView>(R.id.textlevel2).setText("イオラ")
                view.findViewById<TextView>(R.id.textlevel3).setText("イオナズン")
            }
            MagicType.DARK -> {
                view.findViewById<TextView>(R.id.textlevel1).setText("ドルマ")
                view.findViewById<TextView>(R.id.textlevel2).setText("ドルクマ")
                view.findViewById<TextView>(R.id.textlevel3).setText("ドルマドン")
            }
        }
        return view
    }
}
Kotlin

.xmlファイル

activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" />
XML
fragment_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".ui.main.MainFragment">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:gravity="center">

        <TextView
            android:id="@+id/textView2"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="魔法の属性を選択してください"
            android:textSize="24dp" />

        <RadioGroup
            android:id="@+id/magicTypeGroup"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <RadioButton
                android:id="@+id/radioFire"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="メラ" />

            <RadioButton
                android:id="@+id/radioIce"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="ヒャド" />

            <RadioButton
                android:id="@+id/radioWind"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="バギ" />

            <RadioButton
                android:id="@+id/radioElectric"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="デイン" />

            <RadioButton
                android:id="@+id/radioBomb"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="イオ" />

            <RadioButton
                android:id="@+id/radioDark"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="ドルマ" />

        </RadioGroup>

        <Button
            android:id="@+id/decideButton"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="20dp"
            android:text="決定" />
    </LinearLayout>

</androidx.constraintlayout.widget.ConstraintLayout>
XML
activity_sub.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".SubActivity" />
XML
fragment_sub.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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:id="@+id/sub"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".ui.main.SubFragment">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:gravity="center">

        <TextView
            android:id="@+id/textlevel1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textSize="30dp"
            android:text="TextView" />

        <TextView
            android:id="@+id/textlevel2"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textSize="30dp"
            android:text="TextView" />

        <TextView
            android:id="@+id/textlevel3"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textSize="30dp"
            android:text="TextView" />
    </LinearLayout>

</androidx.constraintlayout.widget.ConstraintLayout>
XML

デモ動画

詳細

実際の手順はこんな感じ

画面遷移前(Activity)

  • staticな変数(companion object内に書かれている変数)でキーの文字列を定義する
  • 画面遷移のために遷移先のオブジェクトのintent型のオブジェクトを作成する
  • intent型のオブジェクトのputExtraメソッドに「キー」と「変数」を設定する

画面遷移先(Activity)

  • ActivityのintentのgetExtra系のメソッドで値を取得する

遷移先Fragment(Fragment)(ここは要修正)

  • @JvmStaticをつけた引数付きのnewInstance()を定義
  • SubFragment().apply内にarguments = Bundle().applyを定義し、その中にputExtra系のメソッドで値を取得する
  • onCreateメソッド内でarguments?.letを定義し、その中にitのgetExtra系メソッドと画面遷移前のstaticな変数のキーで渡された値をメンバ変数に代入する

getExtra系メソッド

このメソッドは画面遷移前にputメソッドで設定したデータの型に応じて変わる。
Int型なら「getIntExtra」というように。
ただし、列挙体やクラス名などの場合はgetSerializableExtraメソッドで取得し、型変換を行う。
まとめると以下の表のようになる。

メソッド名用途
getIntExtra
getDoubleExtraなど型によって対応
Int型など、getDoubleExtraなど型によって変わる
getIntArrayExtra
getDoubleArrayExtraなど型によって対応
Int型など、getDoubleArrayExtraなど配列の中身の型によって変わる
getSerializableExtra値を取得した後で「as」を使うことで色々な型に変更できる。
列挙体もこれを使用することで値を渡せる。