AlertDialogからmessageのViewを取得したい


はじめに

AndroidのAlertDialogを使っていると、messageのViewを取得したいことがあります。
検索すると、AlertDialogをそのまま使っているパターンで、messageのTextViewを取得する方法が出てきます。
こんな感じで↓

val builder = AlertDialog.Builder(context).apply {
    setMessage(message)
}
val dialog = builder.show()
val messageView = dialog.findViewById<TextView>(android.R.id.message)

しかし、ダイアログによるとAlertDialogはDialogFragmentで包んであげることが推奨されており、AlertDialogをそのままshow()する場面はあまり多くないと思います(少なくとも私の所属するプロジェクトでは)。
サンプルは以下の通りです(ダイアログから抜粋)。

class FireMissilesDialogFragment : DialogFragment() {

    override fun onCreateDialog(savedInstanceState: Bundle): Dialog {
        return activity?.let {
            // Use the Builder class for convenient dialog construction
            val builder = AlertDialog.Builder(it)
            builder.setMessage(R.string.dialog_fire_missiles)
                    .setPositiveButton(R.string.fire,
                            DialogInterface.OnClickListener { dialog, id ->
                                // FIRE ZE MISSILES!
                            })
                    .setNegativeButton(R.string.cancel,
                            DialogInterface.OnClickListener { dialog, id ->
                                // User cancelled the dialog
                            })
            // Create the AlertDialog object and return it
            builder.create()
        } ?: throw IllegalStateException("Activity cannot be null")
    }
}

問題点

この場合、どうやってmessageのTextViewを取得するか?
DialogFragmentのshowメソッドはvoidなので、冒頭で述べたような方法でshow後にAlertDialogを取得することはできません。DialogFragmentのインスタンスからgetDialog()して、findViewByIdしようとしてもgetDialogがnullを返すようです。
では、どうするか。

結論

DialogFragmentのonStartでfindViewByIdする。

class MyDialog: DialogFragment() {

    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
        return activity?.let {
            AlertDialog
                .Builder(it)
                .setMessage("メッセージ")
                .setPositiveButton("OK", null)
                .create()
        } ?: throw IllegalStateException("Activity cannot be null")
    }

    override fun onStart() {
        super.onStart()
        val textView = (dialog as? AlertDialog)?.findViewById<TextView>(android.R.id.message)
        // 色を変える
        textView?.setTextColor(Color.BLUE)
        // 文字サイズを変える
        textView?.textSize = 40f
    }
}

無事、文字の色とサイズを変更することができました。