【Kotlin/Android Studio】FragmentのイベントをActivityで受け取る方法
この記事からわかること
- Android Studio/KotlinでFragmentのイベントをActivityへ通知する方法
- ボタンクリックを検知して処理を実装する
- リスナーとは?
- interfaceやlateinit、onAttachの使い方
index
[open]
\ アプリをリリースしました /
友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-
posted withアプリーチ
Fragment側で何かしらのイベントが発生したことをActivityで受け取りそれに伴って処理を実行する実装方法をまとめていきます。
環境
- Android Studio:Flamingo
- Kotlin:1.8.20
FragmentのイベントをActivityで受け取る方法
今回は「Fragment側のボタンタップイベントを検知しActivity側のTextViewを変化させる」処理を実装していきます。
今回のポイント
- interfaceでリスナーを用意
- onAttach内でリスナーをセット
- Activity側でリスナーを継承
FragmentのイベントをActivityで受け取る方法はいくつか存在しますが、FragmentとActivityに依存関係が生じないように注意を払う必要があります。そのためFragment⇄Activity
とならないようにFragment⇄listener⇄Activity
とすることで依存し合わないようにしています。
実際に作成するのは以下のような感じです。Fragmentに背景色を指定しないと透けるのを逆手にActivity側に用意したTextViewがFragmentからでも視認できるようになっています。
実装してみる
まずは適当なFragmentクラスを作成します。今回は「TestFragment」としておきました。またそれに付随したレイアウトファイルは作成しておいてください。
この「TestFragment」の中を以下のように変更します。
class TestFragment : Fragment() {
interface eventListener {
fun onClick()
}
private lateinit var listener: eventListener
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_test, container, false)
}
override fun onAttach(context: Context) {
super.onAttach(context)
listener = context as eventListener
if (listener == null) {
throw ClassCastException("$context must implement OnboardSignUpTermsOfServiceListener")
}
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val button:Button = view.findViewById(R.id.frag_button)
button.setOnClickListener {
onClick(it)
}
}
fun onClick(view: View) {
listener?.onClick()
}
}
それではコードの意味をみていきます。
interface
まずはリスナーの定義からです。interface
を先頭に付与することで抽象メソッドを定義しています。実態はここになく継承させることで継承先に抽象メソッドの定義を義務付けることができます。(Swiftでいうprotocol)
おすすめ記事:【Swift】プロトコルの使い方とメリットとは?実装を任意にする方法
interface eventListener {
fun onClick()
}
この場合はonClick
という名前の抽象メソッドのみ用意しています。
lateinit
lateinit
でプロパティを宣言することで初期化タイミングを遅延させています。本来なら宣言時もしくはinit
内で代入が必要ですが、付与したことでonAttach
で初期化を行わせることが可能になっています。
private lateinit var listener: eventListener
onAttach
onAttach
はFragmentのライフサイクルの1つでContextにFragmentがアタッチされた際に呼び出されるライフサイクルイベントです。ここからActivityのContextを参照することが可能になります。
override fun onAttach(context: Context) {
super.onAttach(context)
listener = context as eventListener
if (listener == null) {
throw ClassCastException("$context に eventListenerが継承されていないよ")
}
}
あとはeventListener型にキャストしプロパティに格納しています。キャストが失敗したらActivityが継承していない可能性があるのでエラーをスローしています。
Activity側から検知する
Activity側ではMainActivityクラスにTestFragment.eventListener
を継承させ、定義したonClick
メソッドをoverride
します。あとはその中にイベント検知後に実装したい処理を記述すればFragment側からボタンをクリックされた時にActivity側の処理を走らせることが可能になります。
class MainActivity : AppCompatActivity() ,TestFragment.eventListener{
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val button:Button = findViewById(R.id.done_button)
button.setOnClickListener{
supportFragmentManager.beginTransaction().apply {
add(R.id.main_frame, TestFragment())
addToBackStack(null)
commit()
}
}
}
override fun onClick() {
val text: TextView = findViewById(R.id.activity_text)
text.text = "クリックされたよ"
}
}
今回はボタンでしたがこの方法を使用することでFragmentのさまざまなイベントを検知することができるようになると思います。
参考文献:【Kotlin】Fragment のイベントを Activity で受け取る
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。