【问题标题】:can I get the position of a `View` after layout in SwiftUI?我可以在 SwiftUI 中布局后获取“视图”的位置吗?
【发布时间】:2019-06-09 21:16:04
【问题描述】:

有没有办法在布局后获得View 的框架?我想在布局定位后画一条连接两个视图的线:

看来我在 React 中需要 measure 之类的东西。

【问题讨论】:

  • @Fogmeister 我的意思是连接两个视图的线。我更新了问题。
  • @Fogmeister 图片已添加 :)
  • 啊...我现在明白了。添加图片后更清晰。
  • @MatteoPacini 很抱歉最初不清楚。
  • @Fogmeister 它已经创建了audulus.com :)

标签: ios swift swiftui


【解决方案1】:

使用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)")
        }
    }
}

【讨论】:

  • 您将帧作为字符串返回?
  • 我正在返回一个 Text 视图(即 SwiftUI 的 UILabel 版本),它在屏幕上显示框架作为示例。
  • CoordinateSpace.global 会更好吗?
  • 我假设正在绘制的路径将在局部坐标空间下,因此在局部坐标空间中获取框架也是有意义的。但这真的取决于我认为的视图层次结构。全局在许多情况下都会很有用。
  • 这种方法真的有效吗?您将如何从视图外部访问从 GeometryReader 获得的值?这就是你需要它的地方,对吧?
【解决方案2】:

为了导出“渲染”视图坐标,我为 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: {$0.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 的建议将它们渲染为一个覆盖图像的文本视图。 自然,一旦您对坐标正确感到满意,您就可以删除文本覆盖视图。 希望这会有所帮助

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-12-02
    • 2012-03-02
    • 2016-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多