【Androidアプリ開発】ダイアログを表示する

2023年2月7日

前回はコンテキストメニューの表示をしました。

【Androidアプリ開発】コンテキストメニューを表示する
【Androidアプリ開発】コンテキストメニューを表示する
前回はAVDで日本語入力の手順を紹介しました。 今回は、画面のアイテムを長押しした時に表示されるコンテキストメ…
http://nomux2.net/post-2292/

今回はダイアログ表示をしようと思います。
ダイアログとはこんな感じのものです。

それでは説明していきます。

ダイアログを表示する

まずはダイアログ表示のソースコードを記載します。

まず文字列です。

<resources>
    (省略)

    <string name="dialog_del_title">削除確認</string>
    <string name="dialog_del_btn_ok">削除</string>
    <string name="dialog_del_btn_cancel">キャンセル</string>
    <string name="dialog_del_complete">TODOを削除しました。</string>
    <string name="dialog_del_error">TODOの削除に失敗しました。</string>

</resources>

次にDialogFragmentです。

package com.example.todomanager

import android.app.AlertDialog
import android.app.Dialog
import android.content.DialogInterface
import android.os.Bundle
import androidx.fragment.app.DialogFragment

class TodoDeleteDialogFragment : DialogFragment() {

    private var _id = -1

    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {

        //ダイアログビルダを生成
        val builder = AlertDialog.Builder(activity)
        val args = arguments!!

        //引数を取得する
        val title = args.getString("title")
        _id = args.getInt("id", -1)

        //ダイアログのタイトルを設定
        builder.setTitle(R.string.dialog_del_title)
        //ダイアログのメッセージを設定
        builder.setMessage("${title}を削除してもよろしいですか?")
        //Positive Buttonを設定
        builder.setPositiveButton(R.string.dialog_del_btn_ok, DialogButtonClickLister())
        //Negative Buttonを設定
        builder.setNegativeButton(R.string.dialog_del_btn_cancel, DialogButtonClickLister())

        //ダイアログオブジェクトを生成し、リターン
        val dialog = builder.create()

        return dialog

    }

    private inner class DialogButtonClickLister : DialogInterface.OnClickListener {
        override fun onClick(dialog: DialogInterface, which: Int) {
            when(which) {

                //Positive Buttonならば
                DialogInterface.BUTTON_POSITIVE -> {
                    val mainActivity = activity as MainActivity
                    mainActivity.TodoDelete(_id)
                }

                //Negative  Buttonならば
                DialogInterface.BUTTON_NEGATIVE -> {

                }

            }
        }
    }
}

MainActivityです。

class MainActivity : AppCompatActivity() {

    private val _helper = DatabaseHelper(this)
   
    (省略)

    override fun onContextItemSelected(item: MenuItem): Boolean {

        //長押しされたビューに関する情報が格納されたオブジェクトを取得
        val info = item.menuInfo as AdapterView.AdapterContextMenuInfo
        //長押しされたリストのポジションを取得
        val listPosition = info.position
        //ポジションから選択されたTodoのIDを取得(!!は非nullに変換)
        val id = _listTodoID!![listPosition]

        when(item.itemId) {

            R.id.menuListContextDescription-> {
                ・・・
            }

            R.id.menuListContextUpdate-> {
               ・・・
            }

            R.id.menuListContextDelete-> {
                //削除確認ダイアログフラグメントオブジェクトを生成
                val dialogFragment = TodoDeleteDialogFragment()

                //IDを渡す
                val args = Bundle()
                args.putInt("id", id)           //引数

                //選択しているアイテムのタイトルを取得
                val lvTodoList = findViewById<ListView>(R.id.lvTodoList)
                val title = lvTodoList.getItemAtPosition(listPosition).toString()
                args.putString("title", title)           //引数

                dialogFragment.arguments = args

                //削除確認ダイアログ表示
                dialogFragment.show(supportFragmentManager, "TodoDeleteDialogFragment")
            }
        }

        return super.onContextItemSelected(item)
    }

    //データを取得する関数
    private fun loadTodoList() {
        ・・・
    }

    fun TodoDelete(id :Int)
    {
        if (_helper.deleteTodo(id)) {
            loadTodoList()
            Toast.makeText(applicationContext, R.string.dialog_del_complete, Toast.LENGTH_SHORT).show()
        } else {
            Toast.makeText(applicationContext, R.string.dialog_del_error, Toast.LENGTH_SHORT).show()
        }
    }

}

それでは説明していきます。

Dialogクラスを追加

まずダイアログのクラスを追加します。

javaの「New」-「Kotlin File/Class」を選択します。

「Name」を入力してOKをクリックします。

新しいクラスファイルが作成されます。この時点では以下のようになっているかと思います。

package com.example.todomanager

class TodoDeleteDialogFragment {
}

DialogFragmentを継承する

作成したクラスにDialogFragmentを継承させ、ダイアログ生成処理、ダイアログで選択されたときに呼び出されるリスナを記述します。

class TodoDeleteDialogFragment : DialogFragment() {
    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {

    }

    private inner class DialogButtonClickLister : DialogInterface.OnClickListener {
        override fun onClick(dialog: DialogInterface, which: Int) {
        }
    }
}

リスナとはイベントを見張って検出を行ってくれるものを指します。

ダイアログ生成処理を記述する

ダイアログが作成されるときに処理するonCreateDialog関数を記載します。

    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {

        //ダイアログビルダを生成
        val builder = AlertDialog.Builder(activity)
        val args = arguments!!

        //引数を取得する
        val title = args.getString("title")
        _id = args.getInt("id", -1)

        //ダイアログのタイトルを設定
        builder.setTitle(R.string.dialog_del_title)
        //ダイアログのメッセージを設定
        builder.setMessage("${title}を削除してもよろしいですか?")
        //Positive Buttonを設定
        builder.setPositiveButton(R.string.dialog_del_btn_ok, DialogButtonClickLister())
        //Negative Buttonを設定
        builder.setNegativeButton(R.string.dialog_del_btn_cancel, DialogButtonClickLister())

        //ダイアログオブジェクトを生成し、リターン
        val dialog = builder.create()

        return dialog

    }

上から順に説明していきます。

今回、作成するダイアログはAlertDialogです。あらかじめ基本的なレイアウトが決まっているダイアログです。まずビルダーオブジェクトを作成します。

val builder = AlertDialog.Builder(activity)

次にMainActivityから渡されてきた引数を取得しています。

val args = arguments!!

//引数を取得する
val title = args.getString("title")
_id = args.getInt("id", -1)

タイトル、メッセージ、Positiveボタン(OKなど)、Negativeボタン(キャンセルなど)に表示する文字あるいは、リスナクラスをセットしています。

//ダイアログのタイトルを設定
builder.setTitle(R.string.dialog_del_title)
//ダイアログのメッセージを設定
builder.setMessage("${title}を削除してもよろしいですか?")
//Positive Buttonを設定
builder.setPositiveButton(R.string.dialog_del_btn_ok, DialogButtonClickLister())
//Negative Buttonを設定
builder.setNegativeButton(R.string.dialog_del_btn_cancel, DialogButtonClickLister())

最後にダイアログのオブジェクトを生成してDialogFlagmentに渡しています。

//ダイアログオブジェクトを生成し、リターン
val dialog = builder.create()

return dialog

ダイアログで選択されたときの処理を記述する

リスナのonClick関数に処理を記述します。

private inner class DialogButtonClickLister : DialogInterface.OnClickListener {
    override fun onClick(dialog: DialogInterface, which: Int) {
        when(which) {

            //Positive Buttonならば
            DialogInterface.BUTTON_POSITIVE -> {
                val mainActivity = activity as MainActivity
                mainActivity.TodoDelete(_id)
            }

            //Negative  Buttonならば
            DialogInterface.BUTTON_NEGATIVE -> {

            }

        }
    }
}

whichには選択されたボタンのIDが入っているので条件分岐させています。

activityで呼び出し元のアクティビティが取得できるので、呼び出し元の方で処理をさせています。
キャンセル時には特に処理はないので記述はありません。

when(which) {

    //Positive Buttonならば
    DialogInterface.BUTTON_POSITIVE -> {
        val mainActivity = activity as MainActivity
        mainActivity.TodoDelete(_id)
    }

    //Negative  Buttonならば
    DialogInterface.BUTTON_NEGATIVE -> {

    }
}

MainActivityから呼び出す処理を記述する

呼び出し元は任意の場所に記述します。例ではコンテキストメニューから「削除」を選択されたときに呼び出すようにしました。

//削除確認ダイアログフラグメントオブジェクトを生成
val dialogFragment = TodoDeleteDialogFragment()

//IDを渡す
val args = Bundle()
args.putInt("id", id)           //引数

//選択しているアイテムのタイトルを取得
val lvTodoList = findViewById<ListView>(R.id.lvTodoList)
val title = lvTodoList.getItemAtPosition(listPosition).toString()
args.putString("title", title)           //引数

dialogFragment.arguments = args

//削除確認ダイアログ表示
dialogFragment.show(supportFragmentManager, "TodoDeleteDialogFragment")

まずDialogFragmentオブジェクトを生成します。

//削除確認ダイアログフラグメントオブジェクトを生成
val dialogFragment = TodoDeleteDialogFragment()

次にDialogで渡す引数を設定しています。

//IDを渡す
val args = Bundle()
args.putInt("id", id)           //引数

//選択しているアイテムのタイトルを取得
val lvTodoList = findViewById<ListView>(R.id.lvTodoList)
val title = lvTodoList.getItemAtPosition(listPosition).toString()
args.putString("title", title)           //引数

dialogFragment.arguments = args

最後にダイアログを表示する処理です。

//削除確認ダイアログ表示
dialogFragment.show(supportFragmentManager, "TodoDeleteDialogFragment")

第1引数はFragmentManagerオブジェクトを渡します。これはMainAvtivityのsupportFragmentManagerプロパティをそのまま渡しています。

第2引数はダイアログを識別するためのタグ文字列です。任意の文字列を指定すればいいです。ここではクラス名をそのまま渡しています。

ダイアログから呼ばれる関数を記述

ダイアログ内で処理が完結することができない、または難しい場合はMainActivityに記述するのがいいです。

ここでは削除を選択されたときに対象のTODOを削除する処理を記述しています。
deleteTodoは、自作した関数です。今回の内容と関係ないので割愛します。

fun TodoDelete(id :Int)
{
    if (_helper.deleteTodo(id)) {
        loadTodoList()
        Toast.makeText(applicationContext, R.string.dialog_del_complete, Toast.LENGTH_SHORT).show()
    } else {
        Toast.makeText(applicationContext, R.string.dialog_del_error, Toast.LENGTH_SHORT).show()
    }
}

まとめ

ダイアログが作成できました。

今回は決められたレイアウトで表示するダイアログを紹介しました。
他にも自分でレイアウトしたダイアログを表示することも可能なので機会があったら挑戦してみようと思います。

私自身、Androidアプリ開発は初めてで、Kotlinも初めてなので勉強しながら記事を書いています。
VisualStudioでC#のプログラムを書くのとは全然違うので、大変ですが形が出来上がってくるとテンションあがりますね。

ここまで読んで頂いてありがとうございます。