画面のビュー要素のサイズを取得する
画面のビュー要素のサイズを取得する方法を紹介します。
スクリーンのサイズは、7行目、8行目、に示すように UIScreen.main.bounds.size で取得できます。
ビューを主に配置する領域のサイズは GeometryReader をつかって取得します。この例では ZStack が占める領域のサイズを取得したいので、ソースコードにおいて ZStack を GeometryReader で囲んでいます。
領域を示すプロパティは自動的に geom インスタンスに格納されるので、それを参照します。16行目、17行目が geom インスタンスを参照して ZStack のサイズを取得しているところです。
ちなみに geom はユーザの好みでつけるインスタンス名で、the_geom や my_geom など、任意の名前をつけてください。View の中で複数の GeometryReader を使う時は geom0, geom1, geom2 など、わかりやすいインスタンス名をつけるのが良いでしょう。
ZStack が占める領域以外は、セーフエリアと定義されています。iPhone14 などの機種はセーフエリアが上と下に準備されています。iPhoneSE などの機種はセーフエリアが上にだけ準備されています。
上側のセーフエリアの高さは、geom の safeAreaInsets.top を参照します。
下側のセーフエリアの高さは、geom の safeAreaInsets.bottom を参照します。
それぞれ実行した結果を計算してみましょう。上側のセーフエリアの高さと、ZStackの高さと、下側のセーフエリアの高さが、スクリーンの高さになるはずです。
計算は (( geom.safeAreaInset.top ) + ( geom.size.height ) + ( geom.safeAreaInset.bottom )) で実施します。
iPhone14 の場合は 47 + 763 + 34 で 844 になります。これはスクリーンの高さと同じです。
iPhoneSE の場合は 20 + 647 + 0 で 667 になります。これはスクリーンの高さと同じです。
import SwiftUI
struct ContentView: View {
var body: some View {
let scr_w = UIScreen.main.bounds.size.width
let scr_h = UIScreen.main.bounds.size.height
GeometryReader {
geom in
ZStack{
let geom_w = geom.size.width
let geom_h = geom.size.height
let rct_w0 = geom_w * 1.00
let rct_h0 = geom_h * 1.00
let rct_w1 = geom_w * 0.75
let rct_h1 = geom_h * 0.75
let rct_w2 = geom_w * 0.50
let rct_h2 = geom_h * 0.50
Rectangle()
.frame( width: rct_w0, height: rct_h0 )
.foregroundColor( .green )
Rectangle()
.frame( width: rct_w1, height: rct_h1 )
.foregroundColor( .blue )
Rectangle()
.frame( width: rct_w2, height: rct_h2 )
.foregroundColor( .cyan )
VStack{
let gsai_top = geom.safeAreaInsets.top
let gsai_btm = geom.safeAreaInsets.bottom
Text( String( format: "screen: %.2f * %.2f", scr_w, scr_h ) )
Text( String( format: "rct0: %.2f * %.2f", rct_w0, rct_h0 ) )
Text( String( format: "rct1: %.2f * %.2f", rct_w1, rct_h1 ) )
Text( String( format: "rct2: %.2f * %.2f", rct_w2, rct_h2 ) )
Text( String( format: "safeAreaInsets.top: %.2f", gsai_top ) )
Text( String( format: "safeAreaInsets.bottom: %.2f", gsai_btm ) )
Text( String( format: "debug: %.2f", gsai_top + rct_h0 + gsai_btm ) )
}
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
ちなみに iPhone を回転させたときは下に示すような画面になります。
GeometryReader は、回転も考慮してビューの要素の寸法を示す geom インスタンスを提供してくれますが、スクリーンのサイズを示す UIScreen.main.bounds.size は、縦方向であっても横方向であっても width と height の値は同じになります。
Swift のプログラミングをするまで意識したことがなかったのですが、iPhoneSE は横位置にした場合セーフエリアがなくなるのですね。