飴屋

Kotlin/ダイアログを出す

もう、元からあったボタンを押したときの処理みたいなのを新しいComposableなボタンに関連付けていけば作業も終わりなのかな、って思ってましたが、まだまだやることが出てくるもんですね。

ボタンを押したら確認ダイアログが出て「○○しますけどいいっすか?」と聞いて承認を得る工程がありますよね。間違って実行すると立ち直れなくなるような処理の前で一応確認を取って、責任を担保してもらうアレです。AlertDialogっていうのをこれまで使っていたので、そのまま使おうとしたら、実機でのテストの段でいきなりアプリが停止しました。どうもAppCompat版っていうんですかね、今回Composable版に移行するにあたって捨てた要素に依存している部分らしく、AlertDialogが使えませんでした。いや、正確にはComposable版のAlertDialogを使えってことのようでした。

ちょっと今回はAlertDialogにカスタム動作を仕込みたかったので、MyAlertDialog的な関数でラッピングしてみます。

@Composable
fun MyAlertaDialog(onDismiss: () -> Unit) {
    val context = LocalContext.current
    AlertDialog(
        onDismissRequest = onDismiss,
        title = { Text(stringResource(R.string.title)) },
        text = { Text(stringResource(R.stringmessage)) },
        confirmButton = {
            TextButton(onClick = {
                onDismiss()
                // OKなときの処理
            }) {
                Text(stringResource(R.string.label_ok))
            }
        },
        dismissButton = {
            TextButton(onClick = onDismiss) {
                Text(stringResource(R.string.label_cancel))
            }
        }
    )
}

MyAlertaDialogの引数はダイアログを消す処理が入ります。ダイアログの表示制御はComposable関数的に一つ上の階層で行うので、MyAlertaDialogのソースの中には一切出てこないのです。title やtext スロットはずばりAppCompat版を踏襲しているので移行は簡単でした。ただ、単なるテキストを渡すのではなく、Composalな関数を渡すことになっています。とりあえず{Text()}を渡しておきましたが、もっといろんな物を渡したり、Modifierをいじったりして、見た目をカスタマイズする余地がかなり増えてそうです。

if (showDialog) {
    MyAlertDialog(
        onDismiss = { showDialog= false }
    )
}

ダイアログの呼び出し側ではこんな感じで showDialog というrememberな状態変数を使って表示を切り替えてみました・・・が、ダイアログを開いた瞬間に閉じられてしまいました。あれこれ調べた結果、これはAlertaDialogにまつわる問題ではありませんでした。

Scaffold
  topBar = TopAppBar
    actions = {
      IconButton
      DropdownMenu
        DropdownMenuItem
        AlertaDialog
    }

本筋から離れてしまいますが、↑こんな感じでtopBar 右肩にオプションメニュー(DropdownMenu)をつけて、それが押されたら隣のAlertaDialogを出すような実装にしていたんですね。でも、ダイアログが出た瞬間、押されたDropdownMenuItemと斧親のDropdownMenuはお役御免と消えてしまい、その子孫要素に当たるダイアログが出現した途端に消えた、ってことみたいです。

Scaffold
  topBar = TopAppBar
    actions = {
      IconButton
      DropdownMenu
        DropdownMenuItem
    }
  {
    AlertaDialog
  }

親を変えたら、問題なく表示されるようになりました。しかし、メニューやダイアログみたいな出たり消えたりする要素は、どこに配置するかちゃんと考えないといけなそうですね。親子関係を持たせると危険そうです。

一覧へ