Android ナビゲーショングラフに Dialogを追加する。
- ボタンを押したらダイアログを開く
- YES / NOボタンを押したら、それに対応する処理を Fragmentで実行する
この方法が現時点で一番良いと思う
ダイアログ側
setFragmentResult("Button1", bundleOf("result" to RESULT_OK))
呼び出すフラグメント側
parentFragmentManager.setFragmentResultListener(
"Button1",
viewLifecycleOwner
) { requestKey: String, result: Bundle ->
val retVal = result.getInt("result")
Toast.makeText(requireActivity(), "Button1 - $retVal", Toast.LENGTH_SHORT).show()
}
フラグメント側とダイアログ側で第一引数の requestKeyを一致させる必要がある。
この方法は推奨されない。匿名オブジェクトが再生成されないため。
※ ただまだ確実にクラッシュさせる方法を見つけられていない..
<fragment
android:id="@+id/mainFragment"
android:name="org.nunocky.navigationanddialogfragment.MainFragment"
android:label="MainFragment">
<action
android:id="@+id/action_mainFragment_to_yesNoDialogFragment"
app:destination="@id/yesNoDialogFragment" />
</fragment>
<dialog
android:id="@+id/yesNoDialogFragment"
android:name="org.nunocky.navigationanddialogfragment.YesNoDialogFragment"
android:label="YesNoDialogFragment" />
private fun showDialog() {
findNavController().navigate(R.id.yesNoDialogFragment)
}
まず返り値のクラスを作る
sealed class Result {
object Init : Result()
object Yes : Result()
object No : Result()
}
この返り値を Fragmentと Dialogで共有する。そのために Activityスコープの ViewModelを使う。
ViewModelの定義
class DialogResultViewModel : ViewModel() {
val result = MutableLiveData<YesNoDialogFragment.Result>(YesNoDialogFragment.Result.Init)
}
ViewModelを Fragmentと Dialogで共有する。
private val resultViewModel: DialogResultViewModel by activityViewModels()
Fragmentは viewmodel.resultを observeし、ボタン押下時の挙動を実装する。
resultViewModel.result.observe(viewLifecycleOwner) {
when (it) {
YesNoDialogFragment.Result.Yes -> {
Toast.makeText(requireActivity(), "YES", Toast.LENGTH_SHORT).show()
}
YesNoDialogFragment.Result.No -> {
Toast.makeText(requireActivity(), "NO", Toast.LENGTH_SHORT).show()
}
else -> {
}
}
}
個人的にはこの実装方法は好きではない。むしろ推奨しない。
一番の理由は YesNoDialogを使い回すことができないから。 Android Navigationは、 この例のように汎用的に用いられるダイアログが再利用されることを考慮していない。 再利用性の観点で言えば従来のコールバックを用いる方法のほうが良い。コードも読みやすいし。
結果を viewModelで共有するのも気に入らない。 viewModelを宣言してしまえば他の Fragmentでも結果の変化が見えてしまうというのが気持ち悪い。 この方法が推奨されるというより、今の Navigationの仕組みでは結果を前画面に戻せないので仕方なくこの方法を使っている感がある、
なので個人的にはダイアログは従来のコールバックを用いる方法を使い続けると思う