我可以在 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 的建议将它们渲染为覆盖图像的文本视图。 一旦您对坐标正确感到满意,您自然可以删除文本覆盖视图。 希望这有帮助