駆け出しエンジニアぱかぱかの成長記録

引くほど忘れっぽい新卒2年目駆け出しSEぱかぱかの備忘録です。

【Android】ダイアログ入門

どうも、仕事終わりのぱかぱかです!

今配属されているプロジェクトがまあまあ忙しめで

20時や21時まで帰れないことがほとんどなのですが

今日は定時退社決められました😉

明日お休みということもあり、今日有給とっている人が多いんですよね。

今のプロジェクトは木→水の1週間スクラムアジャイル開発をやっています。

水曜日のスプリントレビューに向けて今日1日足掻いても

できることは限られているというわけで、戦略的退社です笑

春分の日ありがとう。

 

本日はダイアログについて学んだことをメモしていきたいと思います!

ちょうど今日業務で処理中を示すダイアログ表示中にエラーが発生した場合に

エラーのダイアログが表示されないというバグを解消してきたところだったので

めっちゃタイムリーでした。

 

ダイアログって何?

ユーザーによる意思決定や追加情報の入力を求める小さなウィンドウのこと。

ダイアログ  |  Android デベロッパー  |  Android Developers

 

ユーザーの対応を求めるものなので

必ずコンテンツエリアとアクションボタンを持ちます。

 

お試しで作っている「発見した野鳥を記録するアプリ」では

以下のような感じで使ってみました。

ユーザーによる意思決定として、タップした野鳥を

見たい鳥に登録するかキャンセルするかが選べます。

それではダイアログの作り方を順を追ってみていきます。

リストビューの鳥をタップしたときに表示されるダイアログ

①ダイアログ生成クラスを作成

ダイアログを表示するにはまず、DialogFragmentを継承したクラスを作成します。

様々なアクティビティから使われることを想定して

privateなメンバクラスではなくトップレベルクラスで作るのが良いそうです。

(私の業務のプロジェクトではそうなってなかったな…)

 

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


class
FavoriteConfirmDialogFragment: DialogFragment() {
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
// アクティビティがnullでないならばダイアログオブジェクトを生成。
val dialog = activity?.let {
val builder = AlertDialog.Builder(it)
// ダイアログのタイトルを設定。
builder.setTitle(R.string.dialog_title)
// ダイアログのメッセージを登録。
builder.setMessage(R.string.dialog_message)
// Positive Buttonを設定。
builder.setPositiveButton(R.string.dialog_btn_ok, DialogButtonClickListner())
// Negative Buttonを設定。
builder.setNegativeButton(R.string.dialog_btn_ng, DialogButtonClickListner())
// ダイアログオブジェクトを生成。
builder.create()
}
// 生成したダイアログオブジェクトをリターン
return dialog ?: throw java.lang.IllegalStateException("アクティビティがnullです")
}

 

onCreateDialog()メソッドをオーバーライドしてダイアログ生成処理を記述します。

Androidでダイアログを表すクラスはAlertDialogクラスですが

このダイアログオブジェクトはビルダーを用いて生成します。

まずAlertDialog.Builderオブジェクトを生成し、

呼び出し元を表すactivityというプロパティを引数に渡します。

 

activityはNullableプロパティなので

nullチェックとしてセーフコール演算子(?.)let関数を使っています。

val dialog = activity?.let {}

こういうのはKotlinで初めて出会う書き方です…

慣れたら便利なのでしょうね…

let関数はなんらかの変数に対する処理を拡張関数としてまとめて記述する

スコープ関数というものの一種らしいですが、まだletしか出会ったことないです。

 

ビルダーオブジェクトが生成できたら

そこにどんどん表示の設定を行なっていきます。

これはわかりやすいですね。

ボタンに関しては第2引数にボタンタップ時のリスナクラスインスタンスを渡します。

 

// ダイアログのタイトルを設定。
builder.setTitle(R.string.dialog_title)

// ダイアログのメッセージを登録。
builder.setMessage(R.string.dialog_message)

// Positive Buttonを設定。
builder.setPositiveButton(R.string.dialog_btn_ok, DialogButtonClickListner())

// Negative Buttonを設定。
builder.setNegativeButton(R.string.dialog_btn_ng, DialogButtonClickListner())

 

create()メソッドでダイアログオブジェクトが生成され

これがlet関数の戻り値となるので変数dialogに格納されます。

// ダイアログオブジェクトを生成。
builder.create()

 

最後にdialogをonCreateDialog()メソッドの戻り値としてリターンしてあげます。

return dialog ?: throw java.lang.IllegalStateException("アクティビティがnullです")

 

ここでもまた見慣れないエルビス演算子(?:)というのがでてきました。

nullの場合の処理を:以降に書くことができるんですね。

これも実務で見たことがあります。普通に便利じゃん…

 

③ダイアログのボタンタップ処理を記述

// ダイアログのアクションボタンがタップされた時の処理が記述されたメンバクラス。
private inner class DialogButtonClickListner: DialogInterface.OnClickListener {
override fun onClick(dialog: DialogInterface, which: Int){
// トーストメッセージ用文字列を用意。
var msg = ""
// タップされたアクションボタンで分岐。
when(which) {
DialogInterface.BUTTON_POSITIVE ->
msg = getString(R.string.dialog_ok_toast)
DialogInterface.BUTTON_NEGATIVE ->
msg = getString(R.string.dialog_ng_toast)
}
Toast.makeText(activity, msg, Toast.LENGTH_LONG).show()
}
}

ダイアログのタップに対するリスナクラスは

OnClickListnerインターフェースを実装しonClick()メソッドに処理を記述します。

この時onClick()メソッドの第2引数に渡されるwhichを利用して

処理を分岐させるのが効率良いようです。

DialogInterfaceに定数が用意されているので便利です。

今回はボタンタップ時にトーストを表示する処理を書いています。

 

ひとまずこれで、ダイアログが完成しました。

 

 

ダイアログは意外と思っていたよりなんだかごちゃごちゃしていました…

でも、書いてみると頭の中が整理されて良い感じです。

他の方が見てわかりやすいかは別ですが…

 

今日はこれくらいで終わりにしたいと思います。

明日はお休みなので、美容室に行ってカフェでお勉強でもしようかな?

それでは、ここまで読んでくださりありがとうございました。