はじめに
AndroidアプリでDialogFragmentを実装する際、普通の?(はい、いいえの二択のヤツ)ダイアログではなく、EditTextなどを含むダイアログを作成しその値をActivityへ渡す方法です。
やり方はいくつかあるらしいのですが、今回は新しくインターフェースを実装するやり方です。
Fragment自体の実装については割愛する部分が多めです。
おかしな所があれば教えていただけると幸いです!
構成
MainActivity.kt:Fragmentの呼び出しとFragmentから受け取った値を表示するだけ。
CustomDialogFragment.kt:ダイアログ用のFragmentです。
dialog_layout.xml:EditTextを含むダイアログ用のレイアウトファイルです。
レイアウト
先にレイアウトを実装しておきます。
MainActivityはなんでも良いので割愛します。
dialog_layout.xmlはres/layout下に作成します。
<?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>
実装
フラグメントの作成
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側で受け取る
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へ値を渡すことが出来ます。