0
0

More than 1 year has passed since last update.

AlertDialogのカスタマイズその2:戻り値を受け取ろう

Last updated at Posted at 2021-09-20

前の記事ではAlertDialogに引数を渡す方法を紹介しました。
今回は逆にAlertDialogから戻り値を受け取る方法について触れてみたいと思います。

作成するサンプル

Dialog上にEditTextを配置し、そこで入力された値をMainActivityで受け取り、TextViewに表示するアプリを作ります。
アプリ.gif

実装方法

それでは実装方法を見てみましょう。

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を生成し、その中にTextInputLayoutTextInputEditTextを順々に詰めていき、作成したConstraintLayoutsetView()Dialogに設定してあげるイメージでしょうか?

もちろんLinearLayoutでも実装はできますし、ButtonTextView、画像を設定することもできます。

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 )を参考にしています。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0