【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下に作成します。

```xml: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>

```

###実装
#####フラグメントの作成

```kotlin: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側で受け取る

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