- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我试图让 SwiftUI 识别 UIViewRepresentable 的固有大小,但它似乎将其视为框架设置为 maxWidth: .infinity, maxHeight: .infinity
。我创建了一个人为的示例,这是我的代码:
struct Example: View {
var body: some View {
VStack {
Text("Hello")
TestView()
}
.background(Color.red)
}
}
struct TestView: UIViewRepresentable {
func makeUIView(context: UIViewRepresentableContext<TestView>) -> TestUIView {
return TestUIView()
}
func updateUIView(_ uiView: TestUIView, context: UIViewRepresentableContext<TestView>) {
}
typealias UIViewType = TestUIView
}
class TestUIView: UIView {
required init?(coder: NSCoder) { fatalError("-") }
init() {
super.init(frame: .zero)
let label = UILabel()
label.text = "Sed mattis urna a ipsum fermentum, non rutrum lacus finibus. Mauris vel augue lorem. Donec malesuada non est nec fermentum. Integer at interdum nibh. Nunc nec arcu mauris. Suspendisse efficitur iaculis erat, ultrices auctor magna."
label.numberOfLines = 0
label.translatesAutoresizingMaskIntoConstraints = false
label.backgroundColor = .purple
addSubview(label)
translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
widthAnchor.constraint(equalToConstant: 200),
label.leadingAnchor.constraint(equalTo: leadingAnchor),
label.trailingAnchor.constraint(equalTo: trailingAnchor),
label.topAnchor.constraint(equalTo: topAnchor),
label.bottomAnchor.constraint(equalTo: bottomAnchor),
])
}
}
struct Example_Previews: PreviewProvider {
static var previews: some View {
Example()
.previewDevice(PreviewDevice(rawValue: "iPhone 8"))
.previewLayout(PreviewLayout.fixed(width: 300, height: 300))
}
}
编辑:经过进一步检查,我似乎得到了 Unable to simultaneously satisfy constraints.
,其中一个约束是 'UIView-Encapsulated-Layout-Height'
对拉伸(stretch)的约束尺寸。所以我想这可能有助于防止这些限制强加于我的观点?不确定...
最佳答案
使用 .fixedSize()
为我解决了这个问题。
我所做的是使用 UIViewController
,因此 UIView
的情况可能有所不同。我试图实现的是做一个像这样的三明治结构:
SwiftUI => UIKit => SwiftUI
考虑一个简单的 SwiftUI View :
struct Block: View {
var text: String
init(_ text: String = "1, 2, 3") {
self.text = text
}
var body: some View {
Text(text)
.padding()
.background(Color(UIColor.systemBackground))
}
}
设置背景颜色是为了测试外部 SwiftUI 的环境值是否传递给内部 SwiftUI。一般答案是肯定的,但如果您使用 .popover
之类的东西,则需要谨慎。
UIHostingController 的一个优点是您可以使用 .intrinsicContentSize
获得 SwiftUI 的自然大小。这适用于紧凑 View ,例如 Text
和 Image
,或包含此类紧凑 View 的容器。但是,我不确定 GeometryReader
会发生什么。
考虑以下 View Controller :
class VC: UIViewController {
let hostingController = UIHostingController(rootView: Block("Inside VC"))
var text: String = "" {
didSet {
hostingController.rootView = Block("Inside VC: \(text).")
}
}
override func viewDidLoad() {
addChild(hostingController)
view.addSubview(hostingController.view)
view.topAnchor.constraint(equalTo: hostingController.view.topAnchor).isActive = true
view.bottomAnchor.constraint(equalTo: hostingController.view.bottomAnchor).isActive = true
view.leadingAnchor.constraint(equalTo: hostingController.view.leadingAnchor).isActive = true
view.trailingAnchor.constraint(equalTo: hostingController.view.trailingAnchor).isActive = true
view.translatesAutoresizingMaskIntoConstraints = false
hostingController.view.translatesAutoresizingMaskIntoConstraints = false
}
override func viewDidLayoutSubviews() {
preferredContentSize = view.bounds.size
}
}
这里没有什么特别有趣的。我们为 BOTH 我们的 UIView
和 SwiftUI 的托管 UIView
关闭自动调整掩码。我们强制我们的 View 具有与 SwiftUI 相同的自然大小。
稍后我会讨论更新 preferredContentSize
。
一个无聊的VCRep
:
struct VCRep: UIViewControllerRepresentable {
var text: String
func makeUIViewController(context: Context) -> VC {
VC()
}
func updateUIViewController(_ vc: VC, context: Context) {
vc.text = text
}
typealias UIViewControllerType = VC
}
现在来到 ContentView,即外部 SwiftUI:
struct ContentView: View {
@State var alignmentIndex = 0
@State var additionalCharacterCount = 0
var alignment: HorizontalAlignment {
[HorizontalAlignment.leading, HorizontalAlignment.center, HorizontalAlignment.trailing][alignmentIndex % 3]
}
var additionalCharacters: String {
Array(repeating: "x", count: additionalCharacterCount).joined(separator: "")
}
var body: some View {
VStack(alignment: alignment, spacing: 0) {
Button {
self.alignmentIndex += 1
} label: {
Text("Change Alignment")
}
Button {
self.additionalCharacterCount += 1
} label: {
Text("Add characters")
}
Block()
Block().environment(\.colorScheme, .dark)
VCRep(text: additionalCharacters)
.fixedSize()
.environment(\.colorScheme, .dark)
}
}
}
神奇的是,一切正常。您可以更改水平对齐方式或向 View Controller 添加更多字符,并期待正确的布局。
注意事项:
.fixedSize()
才能使用自然大小。否则 View Controller 会占用尽可能多的空间,就像 GeometryReader() 一样。考虑到 .fixedSize()
的文档,这可能不足为奇,但命名很糟糕。我从没想过 .fixedSize()
会是这个意思。preferredContentSize
并保持更新。最初我发现它对我的代码没有视觉影响,但水平对齐似乎是错误的,因为 VCRep
始终将其前导 anchor 用作 VStack
的布局指南。通过 .alignmentGuide
检查 View 尺寸后,发现 VCRep
的尺寸为零。它还显示!由于默认情况下不启用内容剪辑!顺便说一句,如果您遇到 View 高度取决于其宽度的情况,并且您很幸运能够获得宽度(通过 GeometryReader
),您也可以尝试这样做直接在 SwiftUI View 的 body
中自行布局,并将您的 UIView 作为 .background
附加以用作自定义画家。例如,如果您使用 TextKit 来计算您的文本布局,这会起作用。
关于swift - 如何使 SwiftUI UIViewRepresentable View 包含其内容?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58184957/
我是一名优秀的程序员,十分优秀!