1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Qiita全国学生対抗戦Advent Calendar 2023

Day 8

【SwiftUI】自身(View)が親Viewのどこに位置しているかを取得する(iOS17)

Last updated at Posted at 2023-12-08

はじめに

タイトルでちゃんと伝わっているかわからないので記事の内容を見てください笑
(多分伝わってない)

解説

今回重要なのはCoordinateSpaceProtocolです。
これがiOS17で追加されました。

Viewのサイズや位置などの情報を座標空間に変換して、その空間に名前を付けておけるっぽい?です。
その座標空間情報を使って、呼び出し側のViewが座標空間のどの位置にいるのかを取得するのかな

詳しいことはよくわかりませんが、使ってみるとどのような動きができるのかよくわかります。

以下のサンプルはVStackcontainerという名前をつけてVSTack内のTextで表示しています。

Textcontainerという名前の座標空間のどこに位置しているかを取得できていることがわかります。

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()
        }
    }
}

おわり

これはめっちゃ便利なのでは?

公式ドキュメント

1
2
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?