Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
3
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

posted at

updated at

【Kotlin】DialogFragmentからActivityへ値を渡す

はじめに

AndroidアプリでDialogFragmentを実装する際、普通の?(はい、いいえの二択のヤツ)ダイアログではなく、EditTextなどを含むダイアログを作成しその値をActivityへ渡す方法です。
やり方はいくつかあるらしいのですが、今回は新しくインターフェースを実装するやり方です。
Fragment自体の実装については割愛する部分が多めです。
おかしな所があれば教えていただけると幸いです!

構成

MainActivity.kt:Fragmentの呼び出しとFragmentから受け取った値を表示するだけ。
CustomDialogFragment.kt:ダイアログ用のFragmentです。
dialog_layout.xml:EditTextを含むダイアログ用のレイアウトファイルです。

レイアウト

先にレイアウトを実装しておきます。
MainActivityはなんでも良いので割愛します。
dialog_layout.xmlはres/layout下に作成します。

dialog_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">

    <EditText
        android:id="@+id/dialog_text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="@string/hint_dialog_text"
        android:textColor="@color/colorText"
        android:textColorHint="@color/colorHintText"
        />

</LinearLayout>

実装

フラグメントの作成
CustomDialogFragment.kt

class CustomDialogFragment:DialogFragment() {

    public interface DialogListener{
        public fun onDialogPositive(dialog: DialogFragment)//今回は使わない。色んなダイアログで使いまわす際には使います。
        public fun onDialogNegative(dialog: DialogFragment)
        public fun onDialogTextRecieve(dialog: DialogFragment,text: String)//Activity側へStringを渡します。
    }
    var listener:DialogListener? = null

    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
        val builder = AlertDialog.Builder(activity)
        val inflater = activity?.layoutInflater
        val dialogView = inflater?.inflate(R.layout.dialog_layout,null)//作ったダイアログ用のレイアウトファイルを設定します。
        builder.setView(dialogView)
               .setTitle("タイトル")
               .setPositiveButton("決定"){ dialog, id ->
                    val text = dialogView?.findViewById<EditText>(R.id.dialog_text)?.text//EditTextのテキストを取得
                    if (!text.isNullOrEmpty()){//textが空でなければ
                           listener?.onDialogTextRecieve(this,text.toString())
                     }
                }
                .setNegativeButton("キャンセル"){ dialog, id ->
                     listener?.onDialogNegative(this)
                }
        return builder.create()
    }

    override fun onAttach(context: Context) {
        super.onAttach(context)
        try {
            listener = context as DialogListener
        }catch (e: Exception){
            Log.e("ERROR","CANNOT FIND LISTENER")
        }
    }

    override fun onDetach() {
        super.onDetach()
        listener = null
    }
}

複数のダイアログを実装する場合は、setPositiveButtonでOnDialogPositiveとすれば値は渡されず、OnDialogTextRecieveとすればStringが渡せるようになります。
リスナーはonAttachのタイミングでcontext(Activity)を設定することで、ActivityやFragmentの再生成時でも問題なく動いてくれるようです。

Activity側で受け取る
MainActivity.kt

class MainActivity : AppCompatActivity(),CustomDialogFragment.DialogListener {

    //~省略~

    override fun onDialogTextRecieve(dialog: DialogFragment, text: String) {
        //値を受け取る
        Log.d("dialog",text)
    }
    override fun onDialogPositive(dialog: DialogFragment) {
        //実装なし
    }
    override fun onDialogNegative(dialog: DialogFragment) {
        //キャンセル時
    }
}

おしまい

最低限の実装はこれで終わりです。一度実装してしまえばFragment自体はWhen文などで切り分けて使いまわせるので、インターフェースとレイアウトを増やすことで色々なダイアログからActivityへ値を渡すことが出来ます。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
3
Help us understand the problem. What are the problem?