UIViewRepresentable 对视图框架中的变化做出反应

问题描述 投票:0回答:1

我有一个 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)
ios swift swiftui
1个回答
0
投票

我将创建一个自定义

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。

© www.soinside.com 2019 - 2024. All rights reserved.