DialogFragmentのサイズを設定する方法

今日は妙にAndroidのレイアウト調整に苦戦します。。

~~最近flutterとDjangoばかりやってるからAndroidの神様が怒ってるのかもしれません~~


ここに書くのはDialogFragmentのサイズの調整についてです。
xml側にwidth="match_parent"を書いても反映されず、困りました。
調べたところ、下記のようなDialogFragmentのクラス内のonStart()をoverrideして、widthとheightを設定するようです。

~~…こんな不便でしたっけ。。。~~

# DialogFragmentのサイズの調整方法


```kotlin:SomeDialogFragment.kt
class SomeDialogFragment : DialogFragment() {
    override fun onStart() {
        super.onStart()
        val width = resources.displayMetrics.widthPixels - 16
        val height = resources.displayMetrics.heightPixels - 16
        dialog?.window?.setLayout(width, height)
    }
}
 ```

onStart()をoverrideしてごちゃごちゃ書きます。
これでもだいぶめんどくさいのですが、これpx指定なんですよね。。
dpで指定したい。。
ちなみに上記のコードは全画面から16pxだけ上下左右にmarginをあけています。

そもそも、

```kotlin
resources.displayMetrics.widthDips
resources.displayMetrics.heightDips
```
↑こういうのないの？！。。と思ったんですが、どうやらDisplayMetricsクラスを見たところContextなしで動くように作っているようで。。。（dipは端末依存なのでContextが必要ですよね）

仕方がないので頑張って変換しようと思います。

最終的に完成したものは

```kotlin:SomeDialogFragment.kt
class SomeDialogFragment : DialogFragment() {
    override fun onStart() {
        super.onStart()
        context?.also {
            val width = resources.displayMetrics.widthDips(it) - 16
            val height = resources.displayMetrics.heightDips(it) - 16
            dialog?.window?.setLayoutByDips(requireContext(), width, height)
        }
    }
}
```
↑こんな感じでdp指定でdialogFragmentのサイズを変更できるようになりました。

ここに至るまでに拡張をごちゃごちゃやったので、それらの拡張コードを載せておきます。
まずは手始めにpxとdpの変換コードを書きました。

# pxとdpの変換
```kotlin:Context+Extensionx.kt
fun Context.convertDp2Px(dp: Int) : Int {
    val metrics: DisplayMetrics = this.resources.displayMetrics
    return (dp * metrics.density).toInt()
}

fun Context.convertPx2Dp(px: Int) : Int {
    val metrics: DisplayMetrics = this.resources.displayMetrics
    return (px / metrics.density).toInt()
}
```

↑こいつらを使えばpxとdpを相互に変換できます。

次に、DisplayMetricsクラスにdpの単位でwidthやheightを取得できるメソッドを生やしたいですね。


# 全画面サイズをdpで取得する
```kotlin:DisplayMetrics+Extensions.kt
fun DisplayMetrics.widthDips(context: Context) : Int {
    return context.convertPx2Dp(this.widthPixels)
}

fun DisplayMetrics.heightDips(context: Context) : Int {
    return context.convertPx2Dp(this.heightPixels)
}
```
Contextを渡して全画面サイズを取得できるようにしました。

で、最後にどうにかしなきゃいけないのは

```kotlin
dialog?.window?.setLayout(width, height)
```
ここですね。。。
setLayout()にはpixelを指定するので、できればdpで統一したいです。

# WindowクラスのsetLayout()をdpで指定できるようにする

```kotlin:Window+Extensions.kt
fun Window.setLayoutByDips(context: Context, widthDips: Int, heightDips: Int) {
    this.setLayout(
        context.convertDp2Px(widthDips),
        context.convertDp2Px(heightDips)
    )
}
```
※dpで渡されたものをpxに変換して渡してるだけです。


# 上記のdp指定のメソッドを使ってonStart()を書き換えてみる

最初のpxによるdialogのサイズ変更方法は

```kotlin:SomeDialogFragment.kt
class SomeDialogFragment : DialogFragment() {
    override fun onStart() {
        super.onStart()
        val width = resources.displayMetrics.widthPixels - 16
        val height = resources.displayMetrics.heightPixels - 16
        dialog?.window?.setLayout(width, height)
    }
}
 ```

最終的なdpによるdialogのサイズ変更方法は

```kotlin:SomeDialogFragment.kt
class SomeDialogFragment : DialogFragment() {
    override fun onStart() {
        super.onStart()
        context?.also {
            val width = resources.displayMetrics.widthDips(it) - 16
            val height = resources.displayMetrics.heightDips(it) - 16
            dialog?.window?.setLayoutByDips(requireContext(), width, height)
        }
    }
}
```


ちょっと大変でしたが、pxではなくdpでdialogのサイズを調整できるようになりました。

~~探したりないだけでどこかにdp指定でサイズ変更する方法があったりして。。。~~



# 参考
- https://qiita.com/sudo5in5k/items/c89c53555aed2328dddb
- https://qiita.com/SnowMonkey/items/6edcd875d78913c50d62