はじめに
タイトルでちゃんと伝わっているかわからないので記事の内容を見てください笑
(多分伝わってない)
解説
今回重要なのはCoordinateSpaceProtocol
です。
これがiOS17で追加されました。
Viewのサイズや位置などの情報を座標空間に変換して、その空間に名前を付けておけるっぽい?です。
その座標空間情報を使って、呼び出し側のViewが座標空間のどの位置にいるのかを取得するのかな
詳しいことはよくわかりませんが、使ってみるとどのような動きができるのかよくわかります。
以下のサンプルはVStack
にcontainer
という名前をつけてVSTack
内のText
で表示しています。
Text
がcontainer
という名前の座標空間のどこに位置しているかを取得できていることがわかります。
import SwiftUI
struct ContentView: View {
var body: some View {
VStack {
GeometryReader { geometryProxy in
let x = geometryProxy.frame(in: .named("container")).origin.x
let y = geometryProxy.frame(in: .named("container")).origin.y
Text("x: \(x), y: \(y)").background(.red)
}
.padding()
}
.coordinateSpace(.named("container"))
}
}
ScrollView内の複数コンテンツの位置をそれぞれ取得したい
それぞれのコンテンツをGeometryReader
を囲むと取得することができました。
GeometryReader
はサイズを指定しないと広がってしまうので等間隔で配置されてます
import SwiftUI
struct ContentView: View {
var body: some View {
VStack {
GeometryReader { geometryProxy in
let x = geometryProxy.frame(in: .named("container")).origin.x
let y = geometryProxy.frame(in: .named("container")).origin.y
Text("x: \(x), y: \(y)").background(.red)
}
.padding()
GeometryReader { geometryProxy in
let x = geometryProxy.frame(in: .named("container")).origin.x
let y = geometryProxy.frame(in: .named("container")).origin.y
Text("x: \(x), y: \(y)").background(.red)
}
.padding()
GeometryReader { geometryProxy in
let x = geometryProxy.frame(in: .named("container")).origin.x
let y = geometryProxy.frame(in: .named("container")).origin.y
Text("x: \(x), y: \(y)").background(.red)
}
.padding()
}
}
}
GeometryReader
を上に持ってきてそれぞれ座標を取得しようとしても正しく取得できません。
import SwiftUI
struct ContentView: View {
var body: some View {
GeometryReader { geometryProxy in
VStack {
let x = geometryProxy.frame(in: .named("container")).origin.x
let y = geometryProxy.frame(in: .named("container")).origin.y
Text("x: \(x), y: \(y)").background(.red)
Text("x: \(x), y: \(y)").background(.red)
Text("x: \(x), y: \(y)").background(.red)
}
.padding()
}
}
}
おわり
これはめっちゃ便利なのでは?
公式ドキュメント