【发布时间】:2021-07-17 22:19:59
【问题描述】:
我正在尝试在 SwiftUI 视图中使用自定义 UIViewController。我设置了一个UIViewControllerRepresentable 类,它在makeUIViewController 方法中创建UIViewController。这将创建UIViewController 并显示按钮,但是UIViewControllerRepresentable 不占用任何空间。
我尝试使用 UIImagePickerController 代替我的自定义控制器,并且大小正确。我让控制器占用空间的唯一方法是在我的 SwiftUI 视图中的 UIViewControllerRepresentable 上设置一个固定框架,我绝对不想这样做。
注意:我确实需要使用 UIViewController,因为我正在尝试在 SwiftUI 中实现 UIMenuController。除了这个我遇到的尺寸不正确的问题之外,我得到了所有的工作。
这是我的代码:
struct ViewControllerRepresentable: UIViewControllerRepresentable {
func makeUIViewController(context: Context) -> MenuViewController {
let controller = MenuViewController()
return controller
}
func updateUIViewController(_ uiViewController: MenuViewController, context: Context) {
}
}
class MenuViewController: UIViewController {
override func viewDidLoad() {
let button = UIButton()
button.setTitle("Test button", for: .normal)
button.setTitleColor(.red, for: .normal)
self.view.addSubview(button)
button.translatesAutoresizingMaskIntoConstraints = false
button.leadingAnchor.constraint(equalTo: self.view.leadingAnchor).isActive = true
button.trailingAnchor.constraint(equalTo: self.view.trailingAnchor).isActive = true
button.topAnchor.constraint(equalTo: self.view.topAnchor).isActive = true
button.bottomAnchor.constraint(equalTo: self.view.bottomAnchor).isActive = true
}
}
我的 SwiftUI 视图:
struct ClientView: View {
var body: some View {
VStack(spacing: 0) {
EntityViewItem(copyValue: "copy value", label: {
Text("Name")
}, content: {
Text("Random name")
})
.border(Color.green)
ViewControllerRepresentable()
.border(Color.red)
EntityViewItem(copyValue: "copy value", label: {
Text("Route")
}, content: {
HStack(alignment: .center) {
Text("Random route name")
}
})
.border(Color.blue)
}
}
}
截图:
我对 UIKit 没有太多经验 - 我唯一的经验是编写 UIKit 视图以在 SwiftUI 中使用。这个问题很可能与我缺乏 UIKit 知识有关。
提前致谢!
编辑:
这是EntityViewItem 的代码。我还将提供 ClientView 所在的容器视图 - EntityView。
我还清理了其余代码并将对 Entity 的引用替换为硬编码值。
struct EntityViewItem<Label: View, Content: View>: View {
var copyValue: String
var label: Label
var content: Content
var action: (() -> Void)?
init(copyValue: String, @ViewBuilder label: () -> Label, @ViewBuilder content: () -> Content, action: (() -> Void)? = nil) {
self.copyValue = copyValue
self.label = label()
self.content = content()
self.action = action
}
var body: some View {
VStack(alignment: .leading, spacing: 2) {
label
.opacity(0.6)
content
.onTapGesture {
guard let unwrappedAction = action else {
return
}
unwrappedAction()
}
.contextMenu {
Button(action: {
UIPasteboard.general.string = copyValue
}) {
Text("Copy to clipboard")
Image(systemName: "doc.on.doc")
}
}
}
.padding([.top, .leading, .trailing])
.frame(maxWidth: .infinity, alignment: .leading)
}
}
ClientView的容器:
struct EntityView: View {
let headerHeight: CGFloat = 56
var body: some View {
ZStack {
ScrollView(showsIndicators: false) {
VStack(spacing: 0) {
Color.clear.frame(
height: headerHeight
)
ClientView()
}
}
VStack(spacing: 0) {
HStack {
Button(action: {
}, label: {
Text("Back")
})
Spacer()
Text("An entity name")
.lineLimit(1)
.minimumScaleFactor(0.5)
Spacer()
Color.clear
.frame(width: 24, height: 0)
}
.frame(height: headerHeight)
.padding(.leading)
.padding(.trailing)
.background(
Color.white
.ignoresSafeArea()
.opacity(0.95)
)
Spacer()
}
}
}
}
【问题讨论】:
-
您必须比您在此处列出的内容更多,因为您提供的代码不会导致该结果(而且,就此而言,甚至无法编译,因为您已经在
MenuViewController上列出的通用要求不会在任何地方使用)。你能测试一下我们可以运行的minimal reproducible example 中的内容吗? -
您的
ViewControllerRepresentable符合用户界面。发布EntityViewItem和Entity代码,以便我可以无错误地运行您的代码 -
@jnpdx - 我更改了现有代码并添加了更多代码。您应该能够只使用那里的代码进行编译。
-
@udbhateja 阅读了上面的评论。
-
@Timmy 这是一个位于
ScrollView内部的函数。如果没有ScrollView,UIViewControllerRepresentable 会占用所有可用空间(就像 GeometryReader 一样)。所以,在我回答之前有几个问题:1)您是否能够通过frame提供明确的尺寸,或者您不知道它应该是什么尺寸? 2) 您是否有理由有使用UIViewController而不确定`UIView*?
标签: ios swiftui uikit uiviewcontrollerrepresentable