[Kotlin] Activity-Fragment間の画面遷移

本文上広告1



Activity-Fragment画面遷移について

KotlinでActivity-Fragmentの画面遷移を勉強します。主にFragmentの新規追加と編集が今回の肝です。

教科書はnyanさんのJavaの解説コードを自分で勉強しながら、Kotlinに変換して、勉強を進めていきます。ここでは、3つ紹介されていますが、本ページでは主に先の二つを解説します。3つ目は先の2つを理解して実践できれば、自ずとできるかと思います。

またこちらの【Android学習】FragmentをKotlinでやってみるコードも参考にさせていただきました。

ActivityにFragmentを貼り付け

nyanさんのJavaの解説コード [Android] Fragment コードで記述するを参考に、レイアウトの中にFragmentを貼り付けて、Activityの作成段階からFragmentは貼り付けられています。プロジェクトでFragmentを初めてKotlinで追加するのが初めの難関かと思います。それ以外は特に難しいところはないかと。

ActivityからFragmentを『動的』に貼り付け

nyanさんのJavaの解説コード [Android] Activity と Fragment の画面遷移 を参考に、activity_main.xmlの中の”@+id/container”となっている部分FrameLayoutに、ボタンを押した際にFragmentを動的に貼り付けます。(説明のために点線で書きましたが、イメージです。)

戻るボタンで戻ります。

Fragment間の遷移

先ほどの例では、戻るボタンで遷移を戻しましたが、Fragment間の遷移は以下を参考にするとよいかと思います。

このページでは解説等をしませんが、FragmentManagerを使用して、popBackStack(), addToBackStack(null)を使用して、遷移させることになります。上で述べた2例ができていれば、意外に簡単に実装できるのではと考えています。

ActivityにFragmentを貼り付け・実践編

MainActivity.kt

何も触りません。いつも通りEmptyActivityを作成する手順で作成します。

activity_main.xml

ポイントとしては、fragmentのプロパティの中に”android:name”があるので、これから追加するFragmentの名前を追加します。下記のように追加してください。

android:name=”com.example.プロジェクト名の名前.TestFragment”

TestFragmentをプロジェクトに追加する

ここが今回の山場です。

  1. プロジェクトのapp→java(MainActivity.ktの入っているフォルダ)で右クリック→New
  2. 先ほどの続きで、下の方のFragment→Fragment(Blank)を選択 下記画像の赤囲みの部分
  3. FragmentNameを”TestFragment”に変更して、Finishボタンを押してください。
  4. TestFragment.ktが追加されます。ちなみにコードとしては以下のような感じです。これを編集していきます。
package com.example.XXXXXXX

import android.content.Context
import android.net.Uri
import android.os.Bundle
import android.support.v4.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup


// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private const val ARG_PARAM1 = "param1"
private const val ARG_PARAM2 = "param2"

/**
 * A simple [Fragment] subclass.
 * Activities that contain this fragment must implement the
 * [TestFragment.OnFragmentInteractionListener] interface
 * to handle interaction events.
 * Use the [TestFragment.newInstance] factory method to
 * create an instance of this fragment.
 *
 */
class TestFragment : Fragment() {
    // TODO: Rename and change types of parameters
    private var param1: String? = null
    private var param2: String? = null
    private var listener: OnFragmentInteractionListener? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        arguments?.let {
            param1 = it.getString(ARG_PARAM1)
            param2 = it.getString(ARG_PARAM2)
        }
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_test, container, false)
    }

    // TODO: Rename method, update argument and hook method into UI event
    fun onButtonPressed(uri: Uri) {
        listener?.onFragmentInteraction(uri)
    }

    override fun onAttach(context: Context) {
        super.onAttach(context)
        if (context is OnFragmentInteractionListener) {
            listener = context
        } else {
            throw RuntimeException(context.toString() + " must implement OnFragmentInteractionListener")
        }
    }

    override fun onDetach() {
        super.onDetach()
        listener = null
    }

    /**
     * This interface must be implemented by activities that contain this
     * fragment to allow an interaction in this fragment to be communicated
     * to the activity and potentially other fragments contained in that
     * activity.
     *
     *
     * See the Android Training lesson [Communicating with Other Fragments]
     * (http://developer.android.com/training/basics/fragments/communicating.html)
     * for more information.
     */
    interface OnFragmentInteractionListener {
        // TODO: Update argument type and name
        fun onFragmentInteraction(uri: Uri)
    }

    companion object {
        /**
         * Use this factory method to create a new instance of
         * this fragment using the provided parameters.
         *
         * @param param1 Parameter 1.
         * @param param2 Parameter 2.
         * @return A new instance of fragment TestFragment.
         */
        // TODO: Rename and change types and number of parameters
        @JvmStatic
        fun newInstance(param1: String, param2: String) =
            TestFragment().apply {
                arguments = Bundle().apply {
                    putString(ARG_PARAM1, param1)
                    putString(ARG_PARAM2, param2)
                }
            }
    }
}

  1. 追加したTestFragmentを編集します。コメント部分は残しておいてもよいのですが、見やすさのために削除しておきます。 onCreateView()関数以外は削除しました。private変数も削除しています。
package com.example.activity_fragment_transition2

import android.os.Bundle
import android.support.v4.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import kotlinx.android.synthetic.main.fragment_test.*

class TestFragment : Fragment() {

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_test, container, false)
    }
}

  1. 以上で編集は終わりです。これでBuildを行い、実行すると以下のような画像が出てくるかと思います。

ActivityからFragmentを『動的』に貼り付け・実践編

activity_main.xml

nyanさんのJavaの解説コード [Android] Activity と Fragment の画面遷移 を参考にして作成してください。

MainActivity.kt

ポイントは、setOnClickListenerの中ですが、

  • supportFragmentManagerを使用して開始すること
  • R.id.containerに、TestFragment.newInstance(“Fragment”)を設定すること。

かなと思います。


import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import kotlinx.android.synthetic.main.activity_main.*


class MainActivity : AppCompatActivity() {

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

        if(savedInstanceState == null) {

            button.setOnClickListener{
                val fragmentManager = supportFragmentManager
                val fragmentTransaction = fragmentManager.beginTransaction()

                // BackStackを設定
                fragmentTransaction.addToBackStack(null)

                // パラメータを設定
                fragmentTransaction.replace(
                    R.id.container,
                    TestFragment.newInstance("Fragment")
                )
                fragmentTransaction.commit()

            }
        }
    }
}

TestFragmentをプロジェクトに追加する

先ほどの章を参照にプロジェクトに追加してください。レイアウトファイルも参考もとと同じように編集してください。

  1. 追加したTestFragmentを編集します。コメント部分は残しておいてもよいのですが、見やすさのために削除しておきます。private変数, onButtonPressed(), onAttach(), onDetach(),OnFragmentInteractionListener{}を削除しています。
package com.example.XXXXXXX

import android.os.Bundle
import android.support.v4.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import kotlinx.android.synthetic.main.fragment_test.*

class TestFragment : Fragment() {

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_test, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        val args = arguments
        if (args != null) {
            val str = args.getString("Message")
            text_fragment.text = str
        }
    }

    companion object {
        @JvmStatic
        fun newInstance(str: String) : TestFragment =
            TestFragment().apply {
                arguments = Bundle().apply {
                    putString("Message", str)
                }
            }
    }
}

  1. text_fragment.text = strで生成した際に入れた、文字列を取得します。
  2. Javaをコピー&ペーストで変換すると以下のようになりますが、newInstanceの部分はデフォルトで用意された関数をそのままで用いることにしました。.applyは変数を少なくするために用意されている仕組みのようです。
    fun newInstance(str: String): TestFragment {
        // Fragemnt01 インスタンス生成
        val fragment = TestFragment()
        // Bundle にパラメータを設定
        val barg = Bundle()
        barg.putString("Message", str)
        fragment.arguments = barg

        return fragment
    }

  1. こちらはこれで終了です。

そのほか気になったこと

.applyについて

applyは変数を少なくするために用意されている仕組みのようです。少しずつ、覚えていきたいと思います。

Kotlinでスコープ関数「apply」を使えば、一時変数を書かなくてすむの巻

KotlinのRun, Let, Apply, Alsoを使い分け

Bundleについて

Key-Valueペアでデータを放りこんで、取り出す仕組みであると理解しています。

こちらのBundleの解説を参照すると分かりやすいかと思います。

シェアする

  • このエントリーをはてなブックマークに追加

フォローする