AlertDialogで自作Layoutを使う（+ DataBindingも）

Dialog + 自作LayoutだとsetPositiveButtonとかできなくて、ボタンをLayoutに準備してfindViewByIdとかするのが面倒...

AlertDialogならsetPositiveButtonとかできるので、自作Layoutファイルを使って、ダイアログの表示部分だけ自作Layoutにしたかったので、調べたものの備忘録的にまとめました。

AlertDialogに自作Layoutを利用するのと、DataBindingも使いたかったので、それも調べてまとめました。DataBinding使わない場合は不必要な箇所はすっ飛ばしてください。

## ■ まず完成形
AlertDialogに自作レイアウトファイル（今回はTextView2つ）を差し込めるようにします。
名前だよ、の方はViewModel経由で取得するようにDataBindingしています。

![Screenshot_1610806707.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/503267/beac35c6-8d4d-406a-42a1-6fee08140ac5.png)



## ■ DataBinding導入
DataBinding導入でGradleに記入したり、基本があります。
導入についてはこちらの記事がわかりやすかったので、こちらを読んでみてください。

・[とにかく簡単にDataBindingまとめ](https://qiita.com/KIRIN3qiita/items/4a2b16b4ce3c9b1cffd5)


## ■ ViewModelを作成する（使わない場合は飛ばしてOK）

```kotlin:DialogViewModel.kt

/**
 * ダイアログのViewModel
 *
 */
class DialogViewModel: ViewModel() {

   var name = "名前だよ"

}

```



## ■ ダイアログのレイアウト

Bindingも使いたいので、Bindingの際の書き方でレイアウトファイルを書く。（Bindingを詳しく知りたい場合は以下のリンクをどうぞ）
**Android デベロッパー**
・[レイアウトとバインディング式
](https://developer.android.com/topic/libraries/data-binding/expressions?hl=ja
)


Binding使わない場合は、AlertDiaogに入れたいレイアウトだけでOKです。


```xml:dialog_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>

        <variable
            name="viewModel"
            type="パス.DialogViewModel" />

    </data>

    <!-- 中身は適当に変えてください -->
    <LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="400dp"
        android:paddingTop="15dp"
        android:paddingLeft="25dp"
        android:paddingRight="25dp">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textStyle="bold"
            android:layout_marginBottom="10dp"
            android:text="下に名前が出るよ"/>

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@{viewModel.name}"/>

    </LinearLayout>

</layout>
```

## ■ DialogFragmentを作成する

DialogFragmentを継承したクラスを作成します。
onCreateDialogでAlertDialogを返すようにしますが、その際の`setView` に作成したLayoutファイルを入れればOKです。

DataBindingしている場合は、`binding.root`を入れます。

```kotlin:HogeDialog.kt
class HogeDialog : DialogFragment() {

    /** ダイアログのViewModel */
    private val viewModel: DialogViewModel by viewModels( { requireActivity() } )

    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
        // 使用したいレイアウトのbinding
        val binding =
            DialoglayoutBinding.inflate(requireActivity().layoutInflater)

        // ViewModeを使う場合
        // 書かないとレイアウトにviewModel.~ と書いても何も起こらないです。
        binding.viewModel = viewModel

        val builder = AlertDialog.Builder(requireActivity())
            .setView(binding.root) // Viewにbindingのrootをセットする。（もしくは自作したレイアウトファイル）
            .setTitle("タイトルだよ") // タイトルが必要ならセットする
            .setMessage("メッセージはレイアウトより上に出るよ） //必要ならセットする
            .setPositiveButton("OK") { _, _ ->
                // ポジティブボタンタップ時の処理
            }
            .setNegativeButton("Cancel") {_, _ ->
                // ネガティブボタンタップ時の処理
            }
        return builder.create()
    }
}
```



## ■ Dialogを表示する
あとはダイアログを表示するだけです。
場所によって表示方法は異なりますが、私の場合はFragmentで呼んでいるのでその場合の書き方を書きます。

```kotlin:Dialogを表示する
val dialog = HogeDialog()
dialog.show(childFragmentManager, "タグは適当にどうぞ")
```

これで自作のレイアウトを使った（+DataBinding）ダイアログが表示されます。
メッセージを入れると、メッセージはレイアウトより上に出てくるので、そこはご注意ください。

### メッセージなしの場合
![Screenshot_1610806707.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/503267/dc858627-a890-d458-48b8-8814aaf429cf.png)

### メッセージありの場合
![Screenshot_1610806870.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/503267/b1f85713-9153-4a0a-86bf-312b85538308.png)

## ■ まとめ
調べるとやりたいことに対してダイレクトな情報が中々見つからなかったのですが、まとめて見ると大した量ではなかったです。

Bindingとか詳しければそんなに分からなくならないと思いますが、これから使ってみたい場合は迷うかもしれませんので、参考になれば幸いです。（ちょっと調べていた時のサイトは忘れてしまったので、見つかったら貼っておきます）

以上です。