今日は妙にAndroidのレイアウト調整に苦戦します。。
最近flutterとDjangoばかりやってるからAndroidの神様が怒ってるのかもしれません
ここに書くのはDialogFragmentのサイズの調整についてです。
xml側にwidth="match_parent"を書いても反映されず、困りました。
調べたところ、下記のようなDialogFragmentのクラス内のonStart()をoverrideして、widthとheightを設定するようです。
…こんな不便でしたっけ。。。
DialogFragmentのサイズの調整方法
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をあけています。
そもそも、
resources.displayMetrics.widthDips
resources.displayMetrics.heightDips
↑こういうのないの?!。。と思ったんですが、どうやらDisplayMetricsクラスを見たところContextなしで動くように作っているようで。。。(dipは端末依存なのでContextが必要ですよね)
仕方がないので頑張って変換しようと思います。
最終的に完成したものは
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の変換
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で取得する
fun DisplayMetrics.widthDips(context: Context) : Int {
return context.convertPx2Dp(this.widthPixels)
}
fun DisplayMetrics.heightDips(context: Context) : Int {
return context.convertPx2Dp(this.heightPixels)
}
Contextを渡して全画面サイズを取得できるようにしました。
で、最後にどうにかしなきゃいけないのは
dialog?.window?.setLayout(width, height)
ここですね。。。
setLayout()にはpixelを指定するので、できればdpで統一したいです。
WindowクラスのsetLayout()をdpで指定できるようにする
fun Window.setLayoutByDips(context: Context, widthDips: Int, heightDips: Int) {
this.setLayout(
context.convertDp2Px(widthDips),
context.convertDp2Px(heightDips)
)
}
※dpで渡されたものをpxに変換して渡してるだけです。
上記のdp指定のメソッドを使ってonStart()を書き換えてみる
最初のpxによるdialogのサイズ変更方法は
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のサイズ変更方法は
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指定でサイズ変更する方法があったりして。。。