【Android】カスタマイズできる DialogFragment 継承クラスを作る【コピペでOK】
今回やること
DialogFragment
を使ったダイアログを実装します。
ダイアログを表示するには DialogFragment
を継承したクラスを自作する必要がありますが、毎回実装するのが手間なので、コピペで使えるシンプルなクラスを実装してみます。
DialogFragment の罠
この DialogFragment
継承クラスを作るとき、データを引数として渡すことは避けるべきです。ダイアログが表示された状態で画面を回転させるとダイアログも再生成されますが、このとき自動的に引数なしのコンストラクタを呼ぼうとするため、それがないとアプリがクラッシュします。
class SimpleDialogFragment(val title: String, val message: String, ...) : DialogFragment() { // ダメなパターン。DialogFragment の継承クラスは引数なしを実装するべき。 }
DialogFragment
継承クラスを実装するときは必ず引数なしコンストラクタを用意しましょう。
(画面の回転でアクティビティやフラグメントを再生成しない設定をしている場合は関係ありません。)
実装
上記の罠を回避するために、必要なデータはセッターを使ってクラスに渡すようにします。
class SimpleDialogFragment : DialogFragment() { private var title: String = "" private var message: String = "" private var positiveButtonLabel: String = "" private var negativeButtonLabel: String = "" private var positiveButtonClickListener: DialogInterface.OnClickListener? = null private var negativeButtonClickListener: DialogInterface.OnClickListener? = null fun setTitle(title: String) { this.title = title } fun setMessage(message: String) { this.message = message } fun setPositiveButton(label: String, listener: DialogInterface.OnClickListener?) { positiveButtonLabel = label positiveButtonClickListener = listener } fun setNegativeButton(label: String, listener: DialogInterface.OnClickListener?) { negativeButtonLabel = label negativeButtonClickListener = listener } override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { activity ?: throw IllegalStateException("Activity cannot be null.") val builder = AlertDialog.Builder(activity) return builder.setTitle(title) .setMessage(message) .setPositiveButton(positiveButtonLabel, positiveButtonClickListener) .setNegativeButton(negativeButtonLabel, negativeButtonClickListener) .create() } }
使い方
スコープ関数を使うことで、タイトル、メッセージ、ボタンの設定がスマートに記述することができます。
val dialog = SimpleDialogFragment().apply { setTitle("タイトル") setMessage("メッセージ") setPositiveButton("はい", DialogInterface.OnClickListener {dialog, which -> Toast.makeText(this, "はいが押されました。", Toast.LENGTH_LONG).show() }) setNegativeButton("いいえ", null) } dialog.show(supportFragmentManager, "sample_dialg")