【Kotlin/Android Studio】FragmentのイベントをActivityで受け取る方法

この記事からわかること

  • Android Studio/KotlinFragmentイベントActivity通知する方法
  • ボタンクリック検知して処理を実装する
  • リスナーとは?
  • interfacelateinitonAttach使い方

index

[open]

\ アプリをリリースしました /

みんなの誕生日

友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-

posted withアプリーチ

Fragment側で何かしらのイベントが発生したことをActivityで受け取りそれに伴って処理を実行する実装方法をまとめていきます。

環境

FragmentのイベントをActivityで受け取る方法

今回は「Fragment側のボタンタップイベントを検知しActivity側のTextViewを変化させる」処理を実装していきます。

今回のポイント

FragmentのイベントをActivityで受け取る方法はいくつか存在しますが、FragmentとActivityに依存関係が生じないように注意を払う必要があります。そのためFragment⇄ActivityとならないようにFragment⇄listener⇄Activityとすることで依存し合わないようにしています。

実際に作成するのは以下のような感じです。Fragmentに背景色を指定しないと透けるのを逆手にActivity側に用意したTextViewがFragmentからでも視認できるようになっています。

【Kotlin/Android Studio】FragmentのイベントをActivityで受け取る方法

実装してみる

まずは適当なFragmentクラスを作成します。今回は「TestFragment」としておきました。またそれに付随したレイアウトファイルは作成しておいてください。

【Kotlin/Android Studio】Fragmentの実装方法と役割!画面遷移と値を渡す方法

この「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 で受け取る

まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。

ご覧いただきありがとうございました。

searchbox

スポンサー

ProFile

ame

趣味:読書,プログラミング学習,サイト制作,ブログ

IT嫌いを克服するためにITパスを取得しようと勉強してからサイト制作が趣味に変わりました笑
今はCMSを使わずこのサイトを完全自作でサイト運営中〜

New Article

index