我可以在 SwiftUI 中布局后获取 `View` 的位置吗?
can I get the position of a `View` after layout in SwiftUI?
有没有办法在布局后获得 View
的框架?我想在布局定位后绘制一条连接两个视图的线:
看来我在 React 中需要类似 measure
的东西。
使用GeometryReader
获取每个视图的框架,并使用框架确定两个视图之间路径的点。
struct ContentView : View {
var body: some View {
GeometryReader { geometry -> Text in
let frame = geometry.frame(in: CoordinateSpace.local)
return Text("\(frame.origin.x), \(frame.origin.y), \(frame.size.width), \(frame.size.height)")
}
}
}
为了导出 "as rendered" 视图坐标,我为 x,y 坐标创建了一组数组,并将它们保存在模型对象中。但是,我不得不不将它们封装在@Published var 中,而是将它们保持为 "var",否则您将进入更新坐标然后重新渲染视图的无限循环。
使用Apple的'landmark'教程,Model对象修改如下:
import SwiftUI
import Combine
final class UserData: ObservableObject {
@Published var showFavoritesOnly = false
@Published var landmarks = landmarkData
var circleImageX = Array(repeating: 0.0, count:20)
var circleImageY = Array(repeating: 0.0, count:20)
}
然后,每次使用以下代码渲染 CircleImage.swift 时写入这些数组,同样来自 'landmark.swift' 教程,保存帧中点。
import SwiftUI
struct CircleImage: View {
@EnvironmentObject var userData: UserData
var landmark: Landmark
var landmarkIndex: Int {
userData.landmarks.firstIndex(where: {[=11=].id == landmark.id})!
}
var body: some View {
ZStack {
landmark.image
.clipShape(Circle())
.overlay(Circle().stroke(Color.white, lineWidth: 4))
.shadow(radius: 10)
VStack {
GeometryReader { geometry -> Text in
let frame = geometry.frame(in: CoordinateSpace.global)
self.userData.circleImageX[self.landmarkIndex] = Double(frame.midX)
return
Text("\(frame.midX)")
.foregroundColor(.red)
.bold()
.font(.title)
}
.offset(x: 0.0, y: 50.0)
GeometryReader { geometry -> Text in
let frame = geometry.frame(in: CoordinateSpace.global)
self.userData.circleImageY[self.landmarkIndex] = Double(frame.midY)
return
Text("\(frame.midY)")
.foregroundColor(.red)
.bold()
.font(.title)
}
.offset(x: 0.0, y: -50.0)
}
}
}
}`
这不仅保存了渲染坐标,还按照 Jake 的建议将它们渲染为覆盖图像的文本视图。
一旦您对坐标正确感到满意,您自然可以删除文本覆盖视图。
希望这有帮助
有没有办法在布局后获得 View
的框架?我想在布局定位后绘制一条连接两个视图的线:
看来我在 React 中需要类似 measure
的东西。
使用GeometryReader
获取每个视图的框架,并使用框架确定两个视图之间路径的点。
struct ContentView : View {
var body: some View {
GeometryReader { geometry -> Text in
let frame = geometry.frame(in: CoordinateSpace.local)
return Text("\(frame.origin.x), \(frame.origin.y), \(frame.size.width), \(frame.size.height)")
}
}
}
为了导出 "as rendered" 视图坐标,我为 x,y 坐标创建了一组数组,并将它们保存在模型对象中。但是,我不得不不将它们封装在@Published var 中,而是将它们保持为 "var",否则您将进入更新坐标然后重新渲染视图的无限循环。
使用Apple的'landmark'教程,Model对象修改如下:
import SwiftUI
import Combine
final class UserData: ObservableObject {
@Published var showFavoritesOnly = false
@Published var landmarks = landmarkData
var circleImageX = Array(repeating: 0.0, count:20)
var circleImageY = Array(repeating: 0.0, count:20)
}
然后,每次使用以下代码渲染 CircleImage.swift 时写入这些数组,同样来自 'landmark.swift' 教程,保存帧中点。
import SwiftUI
struct CircleImage: View {
@EnvironmentObject var userData: UserData
var landmark: Landmark
var landmarkIndex: Int {
userData.landmarks.firstIndex(where: {[=11=].id == landmark.id})!
}
var body: some View {
ZStack {
landmark.image
.clipShape(Circle())
.overlay(Circle().stroke(Color.white, lineWidth: 4))
.shadow(radius: 10)
VStack {
GeometryReader { geometry -> Text in
let frame = geometry.frame(in: CoordinateSpace.global)
self.userData.circleImageX[self.landmarkIndex] = Double(frame.midX)
return
Text("\(frame.midX)")
.foregroundColor(.red)
.bold()
.font(.title)
}
.offset(x: 0.0, y: 50.0)
GeometryReader { geometry -> Text in
let frame = geometry.frame(in: CoordinateSpace.global)
self.userData.circleImageY[self.landmarkIndex] = Double(frame.midY)
return
Text("\(frame.midY)")
.foregroundColor(.red)
.bold()
.font(.title)
}
.offset(x: 0.0, y: -50.0)
}
}
}
}`
这不仅保存了渲染坐标,还按照 Jake 的建议将它们渲染为覆盖图像的文本视图。 一旦您对坐标正确感到满意,您自然可以删除文本覆盖视图。 希望这有帮助