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

j91ykkif  于 2024-01-05  发布在  Swift
关注(0)|答案(3)|浏览(129)

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

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

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

  1. struct MyViewRepresentable: UIViewRepresentable {
  2. var frame: CGRect
  3. func makeUIView(context: Context) -> UIView {
  4. let myView = MyView(frame: frame)
  5. return view
  6. }
  7. func updateUIView(_ uiView: UIView, context: Context) {}
  8. }


使用方法:

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


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

qhhrdooz

qhhrdooz1#

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

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

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

  1. struct ContentView: View {
  2. var body: some View {
  3. MyViewRepresentable()
  4. .frame(width: 400, height: 250, alignment: .center)
  5. }
  6. }


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

展开查看全部
atmip9wb

atmip9wb2#

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

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

  1. override func viewDidLoad() {
  2. super.viewDidLoad()
  3. // 1. View Hierarchy
  4. self.addChild(self.mySubview)
  5. self.view.addSubview(self.mySubview.view)
  6. self.mySubview.didMove(toParent: self)
  7. // 2. View AutoLayout Constraints
  8. self.mySubview.view.translatesAutoresizingMaskIntoConstraints = false
  9. NSLayoutConstraint.activate([
  10. view.leadingAnchor.constraint(equalTo: self.mySubview.view.leadingAnchor),
  11. view.trailingAnchor.constraint(equalTo: self.mySubview.view.trailingAnchor),
  12. view.topAnchor.constraint(equalTo: self.mySubview.view.topAnchor),
  13. view.bottomAnchor.constraint(equalTo: self.mySubview.view.bottomAnchor)
  14. ])
  15. }

字符串

选项B. viewDidLayoutSubviews内手动设置帧

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

  1. override func viewDidLoad() {
  2. super.viewDidLoad()
  3. // 1. Add your subviews once in `viewDidLoad`
  4. self.addChild(self.mySubview)
  5. self.view.addSubview(self.mySubview.view)
  6. self.mySubview.didMove(toParent: self)
  7. }
  8. override func viewDidLayoutSubviews() {
  9. super.viewDidLayoutSubviews()
  10. // 2. Layout your subviews `viewDidLayoutSubviews`
  11. // Update subview frame size
  12. // Must be done in `viewDidLayoutSubviews`
  13. // 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!
  14. let mySubviewFrame = self.view.bounds
  15. self.mySubview.view.frame = mySubviewFrame
  16. }

补充资源

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

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

展开查看全部
lnvxswe2

lnvxswe23#

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

  1. public func makeUIView(context _: UIViewRepresentableContext< MyViewRepresentable>) -> UIView {
  2. let view = UIView(frame: .zero)
  3. let myView = MyView(frame: frame)
  4. myView.translatesAutoresizingMaskIntoConstraints = false
  5. view.addSubview(myView)
  6. NSLayoutConstraint.activate([
  7. myView.heightAnchor.constraint(equalTo: view.heightAnchor),
  8. myView.widthAnchor.constraint(equalTo: view.widthAnchor),
  9. ])
  10. return view
  11. }
  12. public func updateUIView(_: UIView, context _: UIViewRepresentableContext<MyViewRepresentable>) {}

字符串

相关问题