やること
Fragmentの画面遷移で単純に A -> B の画面遷移と A <- B のように
1つ前の画面に戻るのはすぐ理解できるのに
A -> B -> C の後に A <- (B) <- C のように C から A に戻るのが苦戦するので
メモを残すことにしました。
(Webアプリでよくある
一覧画面(A) -> 詳細画面(B) -> 変更画面(C) -> 確認画面(D) -> 一覧画面(A)
のようなパターンだけど、アプリでも類似のものは意外と出くわす印象があります。)
作ったアプリ
https://github.com/shinya-takano/FragmentSample
単純に画面遷移するアプリですが、
画面Dから画面Aに遷移し、画面B・画面Cには戻れないようにしました。
(よくある、編集中の画面には戻れないようにする作り)
理解したこと
1. FragmentManagerはstackでした
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
Log.d("FragmentD", "onViewCreated")
val backStackEntryCount = getMainActivity()?.supportFragmentManager?.backStackEntryCount ?: 0
for (index in 0 until backStackEntryCount) {
val backStackEntry = getMainActivity()?.supportFragmentManager?.getBackStackEntryAt(index)
Log.d("FragmentD", "index=$index name=${backStackEntry?.name}")
}
このコードのログが以下です。stackだと理解できました..
FragmentD: onViewCreated
FragmentD: index=0 name=FragmentA
FragmentD: index=1 name=FragmentB
FragmentD: index=2 name=FragmentC
FragmentD: index=3 name=FragmentD
2. A画面に戻る場合は、B画面までのstackをpopすると理解すると良さそうです..多分
button3.setOnClickListener {
// fragmentManager から pop したい Fragment の tag を取得(popした後のFragmentが表示される)
val tag = getMainActivity()?.supportFragmentManager?.getBackStackEntryAt(1)?.name
Log.d("FragmentD", "tag=$tag")
getMainActivity()?.supportFragmentManager?.popBackStack(tag, FragmentManager.POP_BACK_STACK_INCLUSIVE)
}
実行時のログは以下のようになります。tagにFragmentBを指定すると、FragmentBまでが消えて、
FragmentAが表示されます。
FragmentD: tag=FragmentB
FragmentA: onCreateView
FragmentA: onViewCreated
所感
画面Aに遷移したいからといって、画面AのFragmentをpopBackStack(tag, FragmentManager.POP_BACK_STACK_INCLUSIVE)してハマってました。
きちんと挙動を理解すれば、癖も把握できるのでやっぱりサンプルで理解を深めるのは
大事だと思いました。
その他
Fragmentの拡張関数を用意しておくと、addBackStackなどは楽そうなので、参考までに。
fun Fragment.getBackStackTag(): String {
return this.javaClass.simpleName
}
fun replaceFragment(fragment: Fragment) {
supportFragmentManager.beginTransaction()
.replace(R.id.container, fragment)
.addToBackStack(fragment.getBackStackTag())
.commit()
}
参考
自分でサンプルコード作る前まではこちらの記事を参考にしてました。
こちらの記事の方がわかりやすいと思います...
https://qiita.com/tomo1139/items/62902093d1850085742d
こちらは内部処理にも言及していて、とても参考になりました。
http://nein37.hatenablog.com/entry/2018/05/06/204943