Fragment 間の遷移 (7) 最終の雛形

2019年12月16日月曜日

Android Kotlin

t f B! P L

概要

 2つのFragmentで間で遷移するアプリの雛形をまとめる。

仕様

  • 2つのFragmentは、それぞれ、MainFragmentとSecondFragmentとする。
  • MainFragment上にボタンがあり、それを押すと SecondFragmentに遷移する。
  • SecondFragmentは何も表示しない。
  • SecondFragmentで戻るボタンを押すと、MainFragment に遷移する。
  • MainFragmentで戻るボタンを押しても、なにも遷移しない。

ファイル生成

プロジェクト生成

 Android Studioで以下の必要なファイルを生成する。 Projectの雛形で、Fragment+ViewModelを使ふが、ViewModeならではのことは、ここでは何もしない。生成されるViewModelのファイルも無視する。

Prjoject雛形 Fragment + ViewModel
Name: InterFragmentTransition
Language: Kotlin
Use androidx.* artifacts: チェック

必要なファイル

以下の6つのファイルを必要な雛形ファイルとする。


ファイル 説明
main_activity.xml 自動生成される。編集不要。Fragmentの入れ物となる id=@+id/containerを定義し提供。
MainActivity.kt 自動生成される。編集必要。containerにFragmentを吹き込み(inflate)し、その後、Fragmentをreplaceする。
main_fragment.xml 自動生成される。編集必要。遷移用のボタンを配置する。
MainFragment.kt 自動生成される。編集必要。ボタン押下のイベントリスナーと、ボタン押下イベント処理の interfaceを追加する。
second_fragment.xml SecondFragmentを新規作成すると一緒に作成される。編集不要。
SecondFragment.kt 自分で生成する。編集不要。


Fragment ファイル生成

  1. Android ⇢ app ⇢ java ⇢ com.example.xxxxx で右クリック
  2. New ⇢ Fragment ⇢ Fragment(BLANK)を選択
  3. ダイアローグで以下を設定
    • Fragment Name:  SecondFragment
    • Create lyaout XML? : チェックつける
    • Fragment Layout Name: fragment_second
    • include fragment factory methods? : チェックはずす
    • include interface callback? : チェックはずす
    • 言語はKotlin
 以上までで必要なファイルはすべてそろふ。

ファイル編集

レイアウトファイル main_fragment.xml

Designモードでボタンを配置するのみ。layoutのidはmain、ボタンのidはここではbuttonMainとする。


<?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">

    <TextView
        android:id="@+id/message"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="MainFragment"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/buttonMain"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="To Second Fragment"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/message"
        app:layout_constraintVertical_bias="0.483" />

</androidx.constraintlayout.widget.ConstraintLayout>


コード ファイル MainFragment.kt

 追加コードは、ボタン押下のイベントリスナーと、ボタン押下の interfaceの定義だけ。


class MainFragment : Fragment() {

    companion object {
        fun newInstance() = MainFragment()
    }

    private lateinit var viewModel: MainViewModel

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        val view = inflater.inflate(R.layout.main_fragment, container, false)
        val button = view.findViewById<Button>(R.id.buttonMain)
        button.setOnClickListener {
            val listener = context as? OnButtonClickListener
            listener?.onButtonClicked()
        }
        return view
    }

    interface OnButtonClickListener {
        fun onButtonClicked()
    }

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

}

  • 13行目〜19行目:編集部分。イベントリスナーの設定。
  • 22行目〜24行目:追加部分。イベント用 interface の定義。

コードファイル MainActivity.kt

MainActivity.ktは以下のやうになる。


class MainActivity : AppCompatActivity(), MainFragment.OnButtonClickListener {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.main_activity)
        if (savedInstanceState == null) {
            supportFragmentManager.beginTransaction()
                .replace(R.id.container, MainFragment.newInstance(), "tagMain")
                .commitNow()
        }
    }

    override fun onButtonClicked() {
        val secondFragment = SecondFragment()
        val transaction = supportFragmentManager.beginTransaction()
        transaction.replace(R.id.container, secondFragment, "tagSecond")
        transaction.addToBackStack(null)
        transaction.commit()
    }

    override fun onBackPressed() {
        val fragment = supportFragmentManager.findFragmentByTag("tagMain")
        if (fragment != null && fragment.isVisible()) {
        // just ignore the Back Button Press
        } else {
            super.onBackPressed()
        }
    }
}


  • 1行目:MainFragmentの中の interfaceを派生。
  • 8行目:replaceの引数として MainFragmentのタグ名を設定
  • 13〜19行目:interfaceの実装。ボタン押下のイベント処理本体。MainからSecondへの遷移をBackStackへ追加。
  • 21〜28行目:MainFragmentの場合は戻るボタンを無視する、の処理を追加。
(了)

アーカイブ