FragmentクラスのonAttachを用いたコールバックの実装方法を説明しています。この方法でFragmentからActivity側のメソッドを実行することが出来ます。また、DialogFragmentでも同様に実装可能です。
概要
FragmentからActivity(呼び出し元)のメソッドを実行します。
初めに以下の準備が必要となります。
- Fragment側に実行したいメソッドを定義したインタフェースを作成する
- Fragment側のonAtatchをoverrideして、インタフェースで定義したメソッドをセットする
- Activity側でインタフェースで定義したメソッドをoverrideして実装する
ここまで出来たら、Fragmentの中の必要なタイミングで実行します。
実装例
レイアウト
activity_main.xml
メインアクテビティのレイアウトです。
上から順番にfragment、TextView、Buttonの3つです。
- fragment
fragmentの領域、fragment内のボタンを押すとTextViewを更新する - TextView
コールバックの動作確認する - Button
dialogを表示する、dialog内のボタンを押すとTextViewを更新する
fragment_sample.xml
フラグメントのレイアウトです。
ボタンを押すと、メインアクテビティのテキストの表示内容を更新します。
dialog_sample.xml
ダイアログのレイアウトです。
Positiveボタン(OKボタン)を押すと、メインアクテビティのテキストの表示内容を更新します。
実装方法
SampleFragment.kt
実装のポイントは以下の点です。
- クラス内で参照できるようにListenerの変数を定義
- Interfaceでメソッドを定義
→MainActivityでoverrideする - onAttachでListenerの変数にセット
→MainActivityでoverrideしたListenerをセットする - ボタンを押したときにInterfaceで定義したメソッドを実行
class SampleFragment : Fragment() { //Listenerをセットする変数 private lateinit var listener: CallbackListener //実行するメソッドを定義したInterface interface CallbackListener { fun updateButtonClickFromFragment() } //この中でListenerにセットする 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")) } } override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { val root: View = inflater.inflate(R.layout.fragment_sample, container, false) //更新用ボタン val buttonUpdate: Button = root.findViewById(R.id.buttonUpdate) buttonUpdate.setOnClickListener { listener.updateButtonClickFromFragment() } return root } }
SampleDialogFragment.kt
Fragmentと実装方法は変わりありません。
class SampleDialogFragment : DialogFragment() { //Listenerをセットする変数 private lateinit var listener: CallbackListener //実行するメソッドを定義したInterface interface CallbackListener { fun updateButtonClickFromFragmentDialog() } //この中でListenerにセットする 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")) } } 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のインタフェースで定義したメソッドをoverrideして実装しています。
- updateButtonClickFromFragment
Fragmentで定義したメソッド - updateButtonClickFromFragmentDialog
FragmentDialogで定義したメソッド
//FragmentのListenerを継承する class MainActivity : AppCompatActivity() , SampleFragment.CallbackListener , SampleDialogFragment.CallbackListener { //Fragmentのボタンを押したときの処理 override fun updateButtonClickFromFragment() { val textView: TextView = findViewById(R.id.textView) textView.text = "Update From Fragment!!" } //FragmentDialogのボタンを押したときの処理 override fun updateButtonClickFromFragmentDialog() { val textView: TextView = findViewById(R.id.textView) textView.text = "Update From FragmentDialog!!" } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) //Dialog表示ボタン val buttonShowDialog: Button = findViewById(R.id.buttonShowDialog) buttonShowDialog.setOnClickListener { val newFragment = SampleDialogFragment() newFragment.show(supportFragmentManager, "test") } } }
実行結果
アプリ起動時
Fragmentのボタンを押したとき
Fragment内のボタン(画面上部)を押すと、中央のテキストの表示が変わっています。FragmentからActivityの更新が行えていることが分かります。
DialogFgmentのボタンを押したとき
DialogFragment内のOKボタンを押すと、中央のテキストの表示が変わっています。DialogFragmentからActivityの更新が行えていることが分かります。
まとめ
FragmentクラスのonAttachを用いたコールバックの実装方法を説明しました。
説明した実装方法を用いると、FragmentからActivity側のメソッドを実行することが出来ます。また、DialogFragmentでも同様に実装可能です。
要点は以下の通りです。
- Fragment側のInterfaceでメソッドを定義する
- Activity側でメソッドを実装する
- onAttachで実装したメソッドを取得して、Fragment側で実行する
Fragment(遷移先)からActivity(呼び出し元)を操作したい場面で活用しましょう。