如何使自定义 UIViewRepresentable 填充其父 VStack 并在其中居中设置自定义子视图?

How to make a custom UIViewRepresentable fill its parent VStack and have custom subview centered in it?

提问人:batman 提问时间:8/28/2023 最后编辑:batman 更新时间:8/28/2023 访问量:58

问:

所以我在我的项目中有以下内容。

  1. ContentView ~ 包含 3 个 vstack。
  2. CustomView ~ 具有固定大小为 300x300 的 containerView 的自定义视图,应始终在 ContentView 中居中
  3. CustomViewRepresentable ~ 一个 UIViewRepresentable,用于将 CustomView 插入到 ContentView 中。

每个代码如下:

内容视图

import SwiftUI
import UIKit

struct ContentView: View {
    
    var body: some View {
        VStack(alignment: .center, spacing: 0) {
            VStack {
                Color.blue
                    .frame(height: 50)
            }
            VStack {
                HStack {
                    Color.green
                        .frame(height: 100)
                    Text("Text")
                    Color.green
                        .frame(height: 100)
                }
            }
            VStack { // content view
                GeometryReader { geometry in
                    VStack {
                        CustomViewRepresentable()
                            .frame(width: geometry.size.width, height: geometry.size.height)
                            .background(.gray)
                            .border(.red, width: 1)
                    }
                    .frame(width: geometry.size.width, height: geometry.size.height)
                }
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

自定义视图

import UIKit

class CustomView: UIView {
    private let containerView = UIView()
    override func layoutSubviews() {
        containerView.center = self.center
    }

    func addContainerView() {
        containerView.frame = CGRect(origin: .zero, size: CGSize(width: 300, height: 300))
        addSubview(containerView)
        containerView.center = self.center
    }
}

CustomViewRepresentable

import UIKit
import SwiftUI

struct CustomViewRepresentable: UIViewRepresentable {
    typealias UIViewType = CustomView
    
    func makeUIView(context: Context) -> CustomView {
        let customView = CustomView(frame: CGRect(x: 0, y: 0, width: 300, height: 300))
        customView.addContainerView()
        return customView
    }

    func updateUIView(_ uiView: CustomView, context: Context) {
        
    }
}

我面临的问题是,除非我使用可表示对象内的框架初始化 CustomView,否则 CustomView 中的 containerView 不会显示。

func makeUIView(context: Context) -> CustomView {
        let customView = CustomView(frame: CGRect(x: 0, y: 0, width: 300, height: 300))

我不明白为什么需要这样做,因为我希望 CustomView 采用它嵌入的 VStack 的整个宽度和高度。因此,我认为只是做

CustomViewRepresentable()
   .frame(width: geometry.size.width, height: geometry.size.height)

在 VStack 内部应该可以工作,但显然它没有。那么,填充其父级同时保持始终居中的最佳方式是什么?CustomViewRepresentablecontainerView

Swift SwiftUI UIView UIViewerable

评论

0赞 Sweeper 8/28/2023
“除非我用可表示的框架初始化 CustomView”否则你会如何初始化它? 对我来说也一样有效。let customView = CustomView()
0赞 batman 8/28/2023
从某种意义上说,它对我不起作用,如果我不设置框架,containerView 根本不会显示。
0赞 Sweeper 8/28/2023
“我不设置框架”是什么意思?请举一个最小的可重现示例
0赞 batman 8/28/2023
在里面,我需要做而不是只是让。只有这样,才会显示 CustomView 中的 containerView。makeUIViewlet customView = CustomView(frame: CGRect(x: 0, y: 0, width: 300, height: 300))customView = CustomView()
0赞 Sweeper 8/28/2023
好吧,我无法复制。容器视图仍会显示。

答:

0赞 Mohd Sultan 8/28/2023 #1

无需提供框架功能。在用我这边的工作替换代码之后。请使用以下代码进行检查。CustomViewfunc makeUIView(context: Context) -> CustomViewlet customView = CustomView(frame: CGRect(x: 0, y: 0, width: 300, height: 300))let customView = CustomView()

康滕维尤

import SwiftUI
import UIKit

struct ContentView: View {
    
    var body: some View {
        VStack(alignment: .center, spacing: 0) {
            VStack {
                Color.blue
                    .frame(height: 50)
            }
            VStack {
                HStack {
                    Color.green
                        .frame(height: 100)
                    Text("Text")
                    Color.green
                        .frame(height: 100)
                }
            }
            VStack { // content view
                GeometryReader { geometry in
                    VStack {
                        CustomViewRepresentable()
                            .background(.gray)
                            .border(.red, width: 1)
                    }
                    .frame(width: geometry.size.width, height: geometry.size.height)
                }
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

自定义视图

import UIKit

class CustomView: UIView {
    private let containerView = UIView()
    override func layoutSubviews() {
        containerView.center = self.center
    }

    func addContainerView() {
        containerView.frame = CGRect(origin: .zero, size: CGSize(width: 300, height: 300))
        addSubview(containerView)
        containerView.center = self.center
    }
}

CustomViewRepresentable

import UIKit
import SwiftUI

struct CustomViewRepresentable: UIViewRepresentable {
    typealias UIViewType = CustomView
    
    func makeUIView(context: Context) -> CustomView {
        let customView = CustomView(frame: CGRect(x: 0, y: 0, width: 300, height: 300))
        customView.addContainerView()
        return customView
    }

    func updateUIView(_ uiView: CustomView, context: Context) {
        
    }
}