はじめに
タイトルでちゃんと伝わっているかわからないので記事の内容を見てください笑
(多分伝わってない)
解説
今回重要なのは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()
}
}
}
おわり
これはめっちゃ便利なのでは?
公式ドキュメント