2019Viewサイズをどうやって知る?UIKitではView自身の座標位置やサイズはUIViewのプロパティとしてframeプロパティやboundsプロパティが定義されそれで取得ができました。SwiftUIのViewには座標位置やサイズを表すプロパティはありません。それらの情報を取りたいときにはどうすればいいのでしょうか?そのための特別のViewがあります。GeometryReaderです。GeometryReaderGeometryReaderは特別なViewで、自身のサイズと座標空間を返す関数をクロージャーとして保持しています。そのクロージャーを通して、自身のViewのサイズや座標位置やRootViewのサイズや座標位置も取得することができます。GeometryReaderを使うとこんなことができるようになります。ScrollViewのスクロールに合わせてコンテンツを操作するスクロールに合わせてコンテンツのパララックス効果ヘッダーをスクロールに合わせて拡大、縮小する横スクロールでコンテンツが真ん中に来たら目立たせるView自身のサイズを取得する特定のビューのキャプチャ画像を取得するUIの表現の幅が広がり便利なアプリが作れそうですね。GeometryReaderの使い方GeometryReaderでViewを作ってみます。\(geometry.size.debugDescription)")}クロージャーの引数のgeometryはGeometryProxyプロトコルに準拠したインスタンスです。このインスタンスからViewのサイズや座標位置を取得できます。自身のViewのサイズを知りたいならgeometry.sizeにアクセスをします。originで表示座標を知ろうGeometryProxyプロトコルにはframeメソッドがあり、RootViewまたは自身の座標空間を取得できます。frameメソッドでViewの座標がどうなっているかを調べましょう。ところでSwiftUIの座標はUIKitと同じく左上から始まります。デフォルトでは表示座標はセーフエリアを除いた領域、ステータスバーの下から始まります。これがorigin座標です。X軸の右側に行くほどX座標の値は増え、Y軸の下側に行くほどY座標の値が増えます。ちなみにviewに対してedgesIgnoringSafeAreaをするとステータスバー含めた領域からorigi座標が計算されます。}}Viewの座標を確認するサンプルコードを見てみましょう。}}上記コードの画面表示はこのようになります。RootViewの座標空間を取得しています。frameメソッドの引数にはCoordinateSpace型を指定できます。.globalはRootViewで.localはそのView自身を表します。Heightの値をTextViewで表示しました。それぞれ下記のような値となっています。これはUIViewのbounds.originがつねに(0,0)であることと同じです。SwiftUIのレイアウトシステムここでSwiftUIのレイアウトシステムを振り返ってみましょう。SwiftUIではこのように解説されていました。Viewの表示領域を決める際にはこのようなステップを通るそうです。子が自身のサイズを親へ送る「お気遣いありがとう。親が親の座標空間に子を配置する「それではお前をここに表示しよう」この処理が大本のRootViewから始まり、すべての子ビューのサイズが決まり、配置をしていくとのことです。(ちなみにRootViewはデフォルトでは端末画面のSafeAreaを抜いた領域です)このシステムのいいところは子がサイズを決めるのでどこでも好きなタイミングでフレームを操作できるサイズ決定を親に依存しなくてすむでそれぞれのビューが親を気にせずサイズを決められるところです。globalは本当にRootView?現状CoordinateSpace型にはドキュメントがありません。.globalのグローバルはRootViewの意味でいいのか疑問を持ちました。検証用のViewをつくってみました。}}GeometryRectangleという色付きの四角のViewに各geometryの情報を出力するコードです。3つの四角いViewを表示しているところでX座標が0,10,40となっています。0)3つ目の青いViewはZStackにネストしていますがZStackはx座標に10、offsetしており、GeometryRectangle自身もx座標に30、offsetしているので合計40の値となっています。一つ上の親ビューからの計算ではなくRootViewからの座標計算になっています。ここからglobalを指定するとRootViewから座標計算されることがわかりました。Max座標GeometryProxyプロトコルのframeメソッドで取得できるものはorigin座標だけでなく、X、Y座標のMin,Mid,Max座標それぞれも取得できます。試しにコードで書いてみましょう。}}画面はこうなります。補足説明を入れるとGeometryReaderに.padding()で上下左右にデフォルトパディングを追加。デフォルトの値は16GlobalのMinXはパディングのデフォルト値が加わって16。MaxXはLocalの値にパディング分の16を足したものになっている。Y座標もGlobalのMinYが96から始まっているのに対してLocalは0。MazYはLocalのものに96を足したものになっている。ScrollViewGeometryReaderで取得できるorigin座標はScrollViewでスクロールすると動的に変更されます。.global).origin.yの値が変更されるのがgif画像からわかります。これを検知することでScrollViewのスクロールに合わせてコンテンツを操作するスクロールに合わせてコンテンツのパララックス効果ヘッダーをスクロールに合わせて拡大、縮小する横スクロールでコンテンツが真ん中に来たら目立たせるView自身のサイズを取得する特定のビューのキャプチャ画像を取得するを実現することができます。次回以降具体的なサンプルを紹介しますのでお楽しみに。これを検知していろいろな動きをつけることができる。一冊でSwiftUIの仕組みがわかる「SwiftUI実践入門」Boothで発売中です。Ghost×SearchClose。