DialogからFragmentを操作する方法を説明しています。
基本的な考え方は↓こちらの、「FragmentからActivityを操作する」方法と同じです。
Fragmentの親子関係について
「Activity→DialogFragment(Fragment)」と「Fragment→DialogFragment(Fragment)」の大きな違いは、Fragment同士で親子関係が存在するという点です。
「(親)Fragment→(子)DialogFragment(Fragment)」の関係となります(親が呼び出し元、子が呼び出し先)。また、Fragmentには”parent〇〇”やchild〇〇”といった属性やメソッドが用意されているため、これにより参照できるようになっています。子Fragmentから親Fragmentを参照する場合は”parent〇〇”、親Fragmentから子Fragmentを参照する場合は”child〇〇”となります。
Activityの場合との違い
「Activity→Fragment」の場合
Fragmentで実行できるように、Activityを取得してメソッドを実行できるようにします。
override fun onAttach(context: Context) { super.onAttach(context) try { //MainActivity(呼び出し元)をListenerに変換する val mainActivity: MainActivity = activity as MainActivity listener = mainActivity } catch (e: ClassCastException) { throw ClassCastException((context.toString() + " must implement NoticeDialogListener")) } }
「Fragment→DialogFragment(Fragment)」の場合
呼び出し元のFragment(親Fragment)を取得するようにします。親Fragmentのインスタンスは”parentFragment”により取得します。
override fun onAttach(context: Context) { super.onAttach(context) try { //parentFragment(呼び出し元)をListenerに変換する val fragment = parentFragment listener = fragment as CallbackListener } catch (e: ClassCastException) { throw ClassCastException((context.toString() + " must implement NoticeDialogListener")) } }
実装例
レイアウト
activity_main.xml
メインアクテビティのレイアウトです。
画面一杯にFragmentを表示しています。
fragment_sample.xml
フラグメントのレイアウトです。
ボタンを押すとDaialogを表示、DialogのPositiveボタン(OKボタン)を押すとテキストの表示内容が変わります。
dialog_sample.xml
ダイアログのレイアウトです。
Positiveボタン(OKボタン)を押すと、フラグメントのテキスト表示内容を更新します。
実装方法
SampleFragment.kt
Dialogの表示とInterface(SampleDialogFragment.CallbackListener)で定義するメソッドの実装をしています。
class SampleFragment : Fragment() , SampleDialogFragment.CallbackListener { override fun updateButtonClickFromFragmentDialog() { val textView = view?.findViewById<TextView>(R.id.textView) if (textView != null) { textView.text = "Update From Dialog!!" } } override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { val root: View = inflater.inflate(R.layout.fragment_sample, container, false) //Dialog表示ボタン val button: Button = root.findViewById(R.id.button) button.setOnClickListener { val newFragment = SampleDialogFragment() newFragment.show(childFragmentManager, "test") } return root } }
SampleDialogFragment.kt
Interfaceの定義とonAttachのoverrideをしています。また、onAttach内では”parentFragment”により、listenerをセットします。
class SampleDialogFragment : DialogFragment() { //Listenerをセットする変数 private lateinit var listener: CallbackListener //実行するメソッドを手議したInterface interface CallbackListener { fun updateButtonClickFromFragmentDialog() } //この中でListenerにセットする override fun onAttach(context: Context) { super.onAttach(context) try { //parentFragment(呼び出し元)をListenerに変換する val fragment = parentFragment listener = fragment as CallbackListener } catch (e: ClassCastException) { throw ClassCastException((context.toString() + " must implement NoticeDialogListener")) } } override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { return activity?.let { val builder = AlertDialog.Builder(it) val inflater = requireActivity().layoutInflater; val root = inflater.inflate(R.layout.dialog_sample, null) //viewにレイアウトをセット builder.setView(root) .setPositiveButton("OK", DialogInterface.OnClickListener { dialog, id -> listener.updateButtonClickFromFragmentDialog() }) .setNegativeButton("CANCEL", DialogInterface.OnClickListener { dialog, id -> getDialog()?.cancel() }) builder.create() } ?: throw IllegalStateException("Activity cannot be null") } }
MainActivity.kt
Fragmentを表示するだけなので、特に処理はありません。
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) } }
実行結果
アプリ起動時
ボタンを押してダイアログを表示します。
DialogFgmentのボタンを押したとき
DialogFragment内のOKボタンを押すと、下部のテキスト表示が変わっています。よって、DialogFragmentからFragmentの更新が行えていることが分かります。
まとめ
DialogからFragmentを操作する方法を説明しました。
基本的な考え方は、「FragmentからActivityを操作する」方法と同じですが、大きな違いはFragment同士で親子関係が存在するという点です。
以下の点を覚えておきましょう。
- 「(親)Fragment→(子)DialogFragment(Fragment)」の関係である(親が呼び出し元、子が呼び出し先)。
- 子Fragmentから親Fragmentを参照する場合は”parent〇〇”、親Fragmentから子Fragmentを参照する場合は”child〇〇”の属性・メソッドを参照する。