前の記事ではAlertDialog
に引数を渡す方法を紹介しました。
今回は逆にAlertDialog
から戻り値を受け取る方法について触れてみたいと思います。
作成するサンプル
Dialog上にEditText
を配置し、そこで入力された値をMainActivity
で受け取り、TextView
に表示するアプリを作ります。
実装方法
それでは実装方法を見てみましょう。
MaterialAlertDialogBuilder()を使う(コードで実装)
Dialog
を表示するボタンがクリックされた時のサンプルは以下の通りです。
ここではコンテンツエリア
に表示するレイアウトは全てコードで実装します。
MainActivity.kt
class MainActivity : AppCompatActivity() {
// (省略)
private fun onButtonClick(view: View){
////// Dialogのコンテンツエリアに設定するレイアウトを作成 ////////////
// ConstraintLayout生成
val constraintLayout = ConstraintLayout(this@MainActivity)
// レイアウトパラメーターの設定
constraintLayout.layoutParams = ConstraintLayout.LayoutParams(
ConstraintLayout.LayoutParams.MATCH_PARENT,
ConstraintLayout.LayoutParams.WRAP_CONTENT
)
// IDの生成
constraintLayout.id = View.generateViewId()
// ConstraintLayoutの生成
val constraintSet = ConstraintSet()
constraintSet.clone(constraintLayout)
// EditTextのレイアウトを作成
val textInputLayout = TextInputLayout(this@MainActivity)
// 表示形式の設定
textInputLayout.boxBackgroundMode = TextInputLayout.BOX_BACKGROUND_OUTLINE
// レイアウトパラメーターの設定
textInputLayout.layoutParams = ConstraintLayout.LayoutParams(
ConstraintLayout.LayoutParams.MATCH_PARENT,
ConstraintLayout.LayoutParams.WRAP_CONTENT
)
// IDの生成
textInputLayout.id = View.generateViewId()
// EditTextの生成
val textInputEditText = TextInputEditText(this@MainActivity)
// IDの生成
textInputEditText.id = View.generateViewId()
// EditTextをEditTextレイアウトに追加
textInputLayout.addView(textInputEditText)
// EditTextレイアウトをConstraintLayoutに追加
constraintLayout.addView(textInputLayout)
/////////////////////////////////////////////////////////////
// Builderオブジェクトの生成
val builder = MaterialAlertDialogBuilder(this@MainActivity)
// Dialogのタイトルを設定
builder.setTitle("文字列を入力してください。")
// 作成したConstraintLayoutをDialogのコンテンツエリアに追加
builder.setView(constraintLayout)
// Positiveボタンの処理を記述
builder.setPositiveButton("OK"){
// TextViewにEditTextで入力された値を直接設定
_,
_ -> findViewById<TextView>(R.id.tvDisplay).text = textInputEditText.text.toString()
}
// ダイアログの表示
val dialog = builder.create()
dialog.show()
}
}
「Dialogのコンテンツエリアに設定するレイアウトを作成」とコメントで囲ってある部分がDialog
のコンテンツエリア
にEditText
を表示させるための処理です。
元となるConstraintLayout
を生成し、その中にTextInputLayout
、TextInputEditText
を順々に詰めていき、作成したConstraintLayout
をsetView()
でDialog
に設定してあげるイメージでしょうか?
もちろんLinearLayout
でも実装はできますし、Button
やTextView
、画像を設定することもできます。
MaterialAlertDialogBuilder()を使う(レイアウトファイルを使用)
上記のやり方ではレイアウトの作成まで全てコードで表現しましたが、もちろんレイアウトファイル(.xml)を使って実装することも可能です。
MainActivity.kt
class MainActivity : AppCompatActivity() {
// (省略)
private fun onButtonClick(view: View){
// Builderオブジェクトの生成
val builder = MaterialAlertDialogBuilder(this@MainActivity)
// Dialogのタイトルを設定
builder.setTitle("文字列を入力してください。")
////// Dialogのコンテンツエリアに設定するレイアウトを作成 ////////////
// Contentレイアウトの作成
val contentLayout = layoutInflater.inflate(R.layout.dialog_customize, null)
// EditTextのViewを取得しておく
val etInput = contentLayout.findViewById<EditText>(R.id.etInput)
/////////////////////////////////////////////////////////////
// 作成したContentLayoutをDialogのコンテンツエリアに追加
builder.setView(contentLayout)
// Positiveボタンの処理を記述
builder.setPositiveButton("OK"){
// TextViewにEditTextで入力された値を直接設定
_,
_ -> findViewById<TextView>(R.id.tvDisplay).text = etInput.text.toString()
}
// ダイアログの表示
val dialog = builder.create()
dialog.show()
}
}
だいぶスリムになりましたね。
コンテンツリア
に表示するレイアウトはinlater
から生成しています。
inflate()
メソッドはID
のほか、親となるView
を引数として与える必要がありますが、ここではnullで問題ありません。
dialog_customize.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText
android:id="@+id/etInput"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
レイアウトファイルは非常にシンプルに、EditText
を実装しているだけです。
もちろん他の画面部品を設定することもできるので、AlertDialog
といえど表現の幅はとても広いです。
DialogFragmentを使用する
参考までにDialogFragment
クラスを生成し、そこからレイアウトを設定するコードも載せておきます。
CustomDialogFragment.kt
class CustomDialogFragment : DialogFragment() {
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
return activity?.let{
// Builderクラスを生成
val builder = AlertDialog.Builder(it)
// Dialogのタイトルを設定
builder.setTitle("文字列を入力してください。")
// inflaterを取得
val inflater = requireActivity().layoutInflater
// Viewを設定
builder.setView(inflater.inflate(R.layout.dialog_customize, null))
// AlertDialogオブジェクトを生成
builder.create()
} ?: throw IllegalStateException("Activity cannot be null")
}
}
inflate
のやり方が上記のものとは少し違う点に注意してください。
参考文献
「MaterialAlertDialogBuilder()を使う(コードで実装) 」は900+ Android Code Snippetsさんの記事「android kotlin - AlertDialog EditText programmatically」( https://android--code.blogspot.com/2020/03/android-kotlin-alertdialog-edittext.html )を参考にサンプルコードを実装させていただきました。
また「DialogFragmentを使用する」の方は公式ドキュメント( https://developer.android.com/guide/topics/ui/dialogs?hl=ja#PassingEvents )を参考にしています。