在UIViewRepresentable SwiftUI中设置自定义UIView框架

j91ykkif  于 9个月前  发布在  Swift
关注(0)|答案(3)|浏览(90)

我尝试使用UIViewRepresentable在SwiftUI中使用我的自定义UIView,我希望我的UIView具有与我在.frame()中设置的大小相同的大小,以便我可以像这样使用它:

MyViewRepresentable()
.frame(width: 400, height: 250, alignment: .center)

字符串
例如,我可以将框架设置为属性:

struct MyViewRepresentable: UIViewRepresentable {
    var frame: CGRect
    func makeUIView(context: Context) -> UIView {
        let myView = MyView(frame: frame)

        return view
    }
    func updateUIView(_ uiView: UIView, context: Context) {}
}


使用方法:

struct ContentView: View {
    var body: some View {
        MyViewRepresentable(frame: CGRect(x: 0, y: 0, width: 400, height: 250))
            .frame(width: 400, height: 250, alignment: .center)
    }
}


这不是一个解决方案,我想知道如何使它正确。

qhhrdooz

qhhrdooz1#

如果MyView具有正确的内部布局(仅取决于自身边界),则不需要外部额外限制,即

struct MyViewRepresentable: UIViewRepresentable {
    func makeUIView(context: Context) -> UIView {
        return MyView(frame: .zero)
    }
    func updateUIView(_ uiView: UIView, context: Context) {}
}

字符串
将精确地在具有400x250框架的情况下进行调整

struct ContentView: View {
    var body: some View {
        MyViewRepresentable()
            .frame(width: 400, height: 250, alignment: .center)
    }
}


如果不是,则内部MyView布局有缺陷。

atmip9wb

atmip9wb2#

如果MyView的回答对你不起作用,那么很可能就像他们说的那样:MyView的内部布局有缺陷。
要解决这个问题,你有几个选择:

选项A.在viewDidLoad中使用AutoLayout约束

override func viewDidLoad() {
    super.viewDidLoad()

    // 1. View Hierarchy
    self.addChild(self.mySubview)
    self.view.addSubview(self.mySubview.view)
    self.mySubview.didMove(toParent: self)
    
    // 2. View AutoLayout Constraints
    self.mySubview.view.translatesAutoresizingMaskIntoConstraints = false
    NSLayoutConstraint.activate([
        view.leadingAnchor.constraint(equalTo: self.mySubview.view.leadingAnchor),
        view.trailingAnchor.constraint(equalTo: self.mySubview.view.trailingAnchor),
        view.topAnchor.constraint(equalTo: self.mySubview.view.topAnchor),
        view.bottomAnchor.constraint(equalTo: self.mySubview.view.bottomAnchor)
    ])
}

字符串

选项B. viewDidLayoutSubviews内手动设置帧

只需在UIViewController中设置viewDidLayoutSubviews中的子视图帧。

override func viewDidLoad() {
    super.viewDidLoad()

    // 1. Add your subviews once in `viewDidLoad`
    self.addChild(self.mySubview)
    self.view.addSubview(self.mySubview.view)
    self.mySubview.didMove(toParent: self)
}

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    // 2. Layout your subviews `viewDidLayoutSubviews`
    // Update subview frame size
    // Must be done in `viewDidLayoutSubviews`
    // Otherwise in `viewDidLoad` the bounds equal `UIScreen.main.bounds`, even if you used explicit frame within SwiftUI and used GeometryReader to pass the `CGSize` yourself to this UIViewController!
    let mySubviewFrame = self.view.bounds
    self.mySubview.view.frame = mySubviewFrame
}

补充资源

  • 基本上你有多种布局方法在iOS.在这里,他们是从最旧/最差到最新/最好的顺序.这种排序是固执己见当然:
    *基于框架的布局.在UIView上手动操作framebounds属性。
    *自动调整掩码。在引擎盖下,autoResizingMask使用古老的Spring和支柱。参见autoResizingMaskthis answerthis article
    *自动布局Constraints
    *自动布局StackView
    *SwiftUI的VStackHStack!这仅适用于SwiftUI,以上所有内容仅适用于UIKit。

也许应该为此做一个小的开发文章。

lnvxswe2

lnvxswe23#

一个简单的黑客,如果你不知道什么是错误的MyView是将其添加到一个UIView内,然后返回它,即

public func makeUIView(context _: UIViewRepresentableContext< MyViewRepresentable>) -> UIView {
    let view = UIView(frame: .zero)
    let myView = MyView(frame: frame)
    myView.translatesAutoresizingMaskIntoConstraints = false
    view.addSubview(myView)
    NSLayoutConstraint.activate([
        myView.heightAnchor.constraint(equalTo: view.heightAnchor),
        myView.widthAnchor.constraint(equalTo: view.widthAnchor),
    ])
    return view
}

public func updateUIView(_: UIView, context _: UIViewRepresentableContext<MyViewRepresentable>) {}

字符串

相关问题