1
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

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

Last updated at Posted at 2020-11-28

はじめに

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へ値を渡すことが出来ます。

1
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?