DialogFragmentは難しいので、1日ぐらいかけていろいろ挙動を知ってみるのが重要なようです。
Androidでダイアログを表示させるためにはAlertDialogをそのまま使うのではなく、DialogFragment()を継承したクラスを利用してその中で利用したほうがいいらしい。実際にAlertDialogをそのまま使っても特に支障は感じなかったが、DialogFragment()のほうを使えと言うことだったので、いろいろ調べてみることに。
DialogFragment()を利用するのは、縦横切り替え時など様々なことに対応させるために必要なようだ。だけど、どのような場面で有効なのかいまいちよくわからなかった。
とりあえず最低限の利用方法はこんな感じ。
ただ動かせられればいいのなら、DialogFragmentを継承したクラスのonCreateDialogをオーバーライドして、その中にいろいろな処理を書き込んでしまえばいい。
ここで大切なのはAlertDialogはandroid.support.v7.app.AlertDialogのものを利用すること。またDialogFragmentはandroid.support.v4.app.DialogFragmentのものを利用する。そしてshow()するときにはsupportFragmentManagerを渡してあげる必要がある。
TestDialogのインスタンスを生成し、プロパティであるmTitleにタイトルを設定しても、スマホを縦横に動かしたときにライフサイクルの関係で再度生成されるためmTitleに保存した内容を消えてしまう。そのため、TestDialogのプロパティに対して、直接的に何かを保存しても利用できない。
なので下記のようにcompanion objectでこのクラスのインスタンスを返すようにして、そのときに受け取った引数を処理を振り分けるためにBundleを利用して、後に発生するイベントで利用する。
DialogFragmentでは、少なくともonCreate、onCreateDialogのメソッド内でメンバ変数に保存すれば、そのデータはスマホを縦横に動かしても保存してくれるようだ。
Androidでダイアログを表示させるためにはAlertDialogをそのまま使うのではなく、DialogFragment()を継承したクラスを利用してその中で利用したほうがいいらしい。実際にAlertDialogをそのまま使っても特に支障は感じなかったが、DialogFragment()のほうを使えと言うことだったので、いろいろ調べてみることに。
DialogFragment()を利用するのは、縦横切り替え時など様々なことに対応させるために必要なようだ。だけど、どのような場面で有効なのかいまいちよくわからなかった。
とりあえず最低限の利用方法はこんな感じ。
ただ動かせられればいいのなら、DialogFragmentを継承したクラスのonCreateDialogをオーバーライドして、その中にいろいろな処理を書き込んでしまえばいい。
ここで大切なのはAlertDialogはandroid.support.v7.app.AlertDialogのものを利用すること。またDialogFragmentはandroid.support.v4.app.DialogFragmentのものを利用する。そしてshow()するときにはsupportFragmentManagerを渡してあげる必要がある。
//DialogFragmentを継承したクラスを作る
class TestDialog() : DialogFragment() {
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
//ここでAlertDialogを利用してダイアログを作る
//引数にnullableは適用できないので!!でnot nullで有ることを指定しておく
val dialogBuilder = AlertDialog.Builder(activity!!)
//ここでAlertDialogに関する処理をしてCreateを返値で渡してあげるだけ
return dialogBuilder.create()
}
}
//アクティビティではインスタンスを生成してshowメソッドを実施するだけ
var dialog: TestDialog = TestDialog()
btnOpenDialog.setOnClickListener {
//androd.support.v7のものを利用する場合はsupportFragmentManagerを渡す必要がある
dialog.show(supportFragmentManager, "dialog")
}
DialogFragmentは縦横の切り替え時の作業も裏でやってくれているため、端から見るとからり不自然な動作をする。具体的にはこのような感じ。TestDialogのインスタンスを生成し、プロパティであるmTitleにタイトルを設定しても、スマホを縦横に動かしたときにライフサイクルの関係で再度生成されるためmTitleに保存した内容を消えてしまう。そのため、TestDialogのプロパティに対して、直接的に何かを保存しても利用できない。
class TestDialog() : DialogFragment() {
var mTitle: String = ""
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val dialogBuilder = AlertDialog.Builder(activity!!)
//タイトルとメッセージ
dialogBuilder.setTitle(mTitle)
return dialogBuilder.create()
}
}
ライフサイクルの関係上、再生成されるのでコンストラクタに引数を利用することも不可能な模様。では、どのように処理を振り分ければいいのかというと、companion objectを利用してそこで受け取った引数をBundleを利用してデータを渡してあげればいいらしい。なので下記のようにcompanion objectでこのクラスのインスタンスを返すようにして、そのときに受け取った引数を処理を振り分けるためにBundleを利用して、後に発生するイベントで利用する。
DialogFragmentでは、少なくともonCreate、onCreateDialogのメソッド内でメンバ変数に保存すれば、そのデータはスマホを縦横に動かしても保存してくれるようだ。
class TestDialog() : DialogFragment() {
//ダイアログのタイトルを保存する変数 ただここにタイトルを保存しただけではスマホ縦横時に消えてしまう
var mTitle: String by Delegates.notNull<String>()
//コンストラクタで引数を渡すことができないのでBuilderパターンを利用する
companion object {
//Builderでタイトルを渡し上げて、このクラスのインスタンスを返してあげる
fun Builder(title: String): TestDialog {
//Bundleを利用してタイトルを一時的に保存する
val bundle: Bundle = Bundle().also { it.putString("Title", title) }
val testDialog: TestDialog = TestDialog().also { it.arguments = bundle }
return testDialog
}
}
//onCreate内でメンバ変数に保存すれば、スマホを横に動かしても保存される
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//argumentsから保存したタイトル名を取得するのでメンバ変数に保存する
mTitle = arguments?.getString("Title") as String
}
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val dialogBuilder = AlertDialog.Builder(activity!!)
//タイトルを設定する
dialogBuilder.setTitle(mTitle)
return dialogBuilder.create()
}
}