LoginSignup
0
0

More than 1 year has passed since last update.

AlertDialogのカスタマイズその1:引数を渡そう

Posted at

何かと便利なAlertDialogですが、引数を渡してその内容を表示させることも簡単にできます。
ViewBindingを使い柔軟にカスタマイズすることもできますが、今回はシンプルにテキストのみを呼び出し元から渡すサンプルを実装してみたいと思います。

AlertDialogについて

基本的にAndroidのDialogはタイトルコンテンツエリアPositiveButtonNegativeButtonNeutralButtonといった部品で構成されています(ボタンの総称をActionButtonとも言います)。
ダイアログサンプル.png
DialogとしてはAlertDialogが最もよく使われ、Alertとはありますが別に警告に限らず様々な用途で使うことができます。

今回はMainAcitivtyMaterialAlertDialogBuilder()を使用する方法と、DialogFragmentを使う方法の2種類を紹介します。

作成するサンプル

ListViewに英単語の一覧を表示し、アイテムをクリックするとAlertDialogが起動し、その単語の品詞、意味を表示するサンプルを作成します。
なおListViewのカスタマイズについては本記事では触れません。
単語帳.gif

なお今回紹介する2つの方法どちらも同じ動きをします。

コード

それでは両者のコードを見てみましょう。

MaterialAlertDialogBuilder()で実装

たぶん一番楽なやり方です。

MainActivity.kt

class MainActivity : AppCompatActivity() {

    // (省略)

    private inner class ListItemClickListener : AdapterView.OnItemClickListener{
        // リストのアイテムがクリックされたときのイベントハンドラ
        override fun onItemClick(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
            val item = parent?.getItemAtPosition(position) as MutableMap<String, Any>
            val wordName = item["name"] as String
            val wordSpeech = item["speech"] as String
            val wordMeaning = item["meaning"] as String

            val builder = MaterialAlertDialogBuilder(this@MainActivity)
            builder.setTitle(wordName)
            builder.setMessage("$wordSpeech:$wordMeaning")
            val dialog = builder.create()
            dialog.show()
        }
    }
}

シンプルですね。
MaterialAlertDialogBuildercontextを渡しbuilderオブジェクトを生成します。
生成したオブジェクトにsetTitle()setMessage()で値を設定するだけですね。
ただまぁ「引数を渡す」ってのとはちょっとイメージが違うか。
今回は触れていませんがもちろん各ボタンがクリックされた場合の処理もMainAcitivty内部に記述できます。

DialogFragmentで実装

ちゃんと(?)DialogFragmentを生成し、そこに引数を渡します。
拡張性はこちらの方が高いですね。

WordDialogFragment.kt

class WordDialogFragment : DialogFragment() {

    // 表示する「単語」、「品詞」、「意味」のプロパティ
    private var _word: String = ""
    private var _speech: String = ""
    private var _meaning: String = ""

    companion object{
        // インスタンス生成のメソッド
        // 引数として読みだし元から「単語」、「品詞」、「意味」を受け取る
        fun create(word: String, speech: String, meaning:String): WordDialogFragment{
            val bundle = Bundle()
            bundle.putString("Word", word)
            bundle.putString("Speech", speech)
            bundle.putString("Meaning", meaning)
            val dialog = WordDialogFragment().also { it.arguments = bundle }
            return dialog
        }
    }

    // 引数の内容をプロパティに設定
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        _word = arguments?.getString("Word") as String
        _speech = arguments?.getString("Speech") as String
        _meaning = arguments?.getString("Meaning") as String
    }

    // ダイアログの表示
    // プロパティから画面部品に値を設定
    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
        val dialog =  activity?.let{
            val builder = AlertDialog.Builder(it)
            builder.setTitle(_word)
            builder.setMessage("$_speech:$_meaning")
            builder.create()
        }
        return dialog ?: throw IllegalStateException("Error")
    }
}

すこし注意していただきたいのがメンバ変数にあたる_word_speech_meaningのデータの持ち方(与え方?)です。
コンストラクタの引数としてこれらのデータを受け取り、onCreateDialogsetTitle()しようとすると画面回転させたときにアプリが落ちます

というのもDialogFragment(実際にはそれ以外にもFragmentを継承しているクラスも)は、画面を回転させたりするとActivityが破棄され、そしてその都度再度生成される動きとなっているからです。
そしてその際の初期化は引数なしのコンストラクタで行われます。
なので落ちちゃうんですね。

というわけで今回のサンプルではonCreateで引数をメンバ変数に設定し、onCreateDialogでタイトル、メッセージにsetするという書き方をしています。

MainActivity.kt

Dialogの生成は以下の通りです。

class MainActivity : AppCompatActivity() {

    // (省略)

    private inner class ListItemClickListener : AdapterView.OnItemClickListener{
        // リストのアイテムがクリックされたときのイベントハンドラ
        override fun onItemClick(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
            val item = parent?.getItemAtPosition(position) as MutableMap<String, Any>
            val wordName = item["name"] as String
            val wordSpeech = item["speech"] as String
            val wordMeaning = item["meaning"] as String

            // ダイアログの生成
            var dialogFragment = WordDialogFragment.create(wordName, wordSpeech, wordMeaning)
            dialogFragment.show(supportFragmentManager, "WordDialog")
        }
    }
}

こちらはDialogFragmentを呼び出しているだけですね。
create()メソッドで引数を渡すのだけ忘れないでください。

まとめ

シンプルに引数を渡して表示するだけの内容ですが、DialogFragment側でのデータの持ち方に少し工夫が必要ですね。
次はDialogから引数を受け取る方法についてまとめてみたいと思います。

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