我有一个 UIView,它使用路径在 CALayer 上绘制一些内容。对于正确的绘图尺寸,它取决于视图的框架。
现在我尝试在 SwiftUI 中使用此视图,为此我使用
UIViewRepresentable
。我的第一个问题是我无法获得正确的视图框架,但是我通过将可表示的视图包装在 GeometryReader
中来解决这个问题,在我看来这不是最好的,但它有效。现在的问题是,当我的视图改变大小(例如屏幕旋转)时,我不知道如何接收通知,以便更新我的绘图。
据我了解,除非视图层次结构的某些状态发生变化,否则不会调用
updateUIView(_:)
方法,并且它似乎不会在旋转时被调用。
struct MyRepresentable: UIViewRepresentable {
var geometry: GeometryProxy
func makeUIView(_ view: UIView, context: Context) -> UIView {
let view = UIView()
let size = geometry.size
view.frame = CGRect(x: 0, y: 0, width: size.width, height: size.height)
context.coordinator.view = view
context.coordinator.draw()
return view
}
func updateUIView(_ view: UIView, context: Context) {
let size = geometry.size
context.coordinator.view.frame = CGRect(x: 0, y: 0, width: size.width, height: size.height)
context.coordinator.update()
}
}
编辑:
draw 方法看起来像这样:
// locations is [CLLocation]
let points = locations.map { $0.cgPoint }
let path = CGMutablePath()
path.move(to: points[0])
for index in 1..<points.count {
path.addLine(to: points[index])
}
var transform = getTransformation(for: path)
let transformedPath = path.copy(using: &transform)
let newLayer = CAShapeLayer()
newLayer.path = transformedPath
newLayer.strokeColor = UIColor.white.cgColor
newLayer.fillColor = UIColor.clear.cgColor
newLayer.lineWidth = 6
self.view.layer.addSublayer(newLayer)
我将创建一个自定义
UIView
并在其 draw
方法中进行绘图。
class MyView: UIView {
var locations: [CLLocation] = []
override func draw(_ rect: CGRect) {
// put your drawing logic here...
// you can access self.bounds here!
let points = locations.map { $0.cgPoint }
let path = CGMutablePath()
path.move(to: points[0])
for index in 1..<points.count {
path.addLine(to: points[index])
}
var transform = getTransformation(for: path)
let transformedPath = UIBezierPath(cgPath: path.copy(using: &transform))
UIColor.white.setStroke()
transformedPath.lineWidth = 6
transformedPath.stroke()
}
}
struct MyRepresentable: UIViewRepresentable {
func makeUIView(_ view: MyView, context: Context) -> MyView {
let view = MyView()
// this is so that 'draw' is called every time the frame of the view changes
view.contentMode = .redraw
return view
}
func updateUIView(_ view: MyView, context: Context) {
view.locations = someUpdatedLocations
}
}
还可以考虑使用 SwiftUI
Canvas
来进行绘图。 Canvas
的大小作为其闭包参数之一给出,您可以使用 UIHostingController
将其移植到 UIKit。