I have a UIViewRepresentable
wrapping an UIView
that contains a UILabel
.
I'm trying to position this representable view inside a HStack
and I'd like it to take the width of the underlying label.
Here is the demo code:
import SwiftUI
struct MyView1: UIViewRepresentable {
typealias UIViewType = UIView1
func makeUIView(context: Context) -> UIView1 {
return UIView1()
}
func updateUIView(_ nsNumber: UIView1, context: Context) {}
}
class UIView1: UIView {
public var label: UILabel
init() {
self.label = UILabel()
label.text = "Hello, World!"
super.init(frame: .zero)
addSubview(label)
}
@available(*, unavailable)
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
struct ContentView: View {
var body: some View {
HStack {
Text("Push")
.background(.green)
Spacer()
MyView1()
.fixedSize()
.background(.blue)
}
}
}
#Preview { ContentView() }
The issue is that the view MyView1
doesn't appear in the stack at all.
Any idea how it could be achieve? I just want my MyView1
to just take the space of the label.
You should override sizeThatFits
in UIViewRepresentable
. You should return the desired size of the view, given a ProposedViewSize
.
With fixedSize()
, sizeThatFits
will receive a ProposedViewSize
with both width
and height
being nil
.
It's not clear what you want to happen when there is no fixedSize()
. Let's say you want the label to expand horizontally as much as possible. An example implementation of that is:
func sizeThatFits(_ proposal: ProposedViewSize, uiView: UIView1, context: Context) -> CGSize? {
let size = uiView.label.intrinsicContentSize
return CGSize(width: max(size.width, proposal.width ?? 0), height: size.height)
}
You should also set up some constraints between self.label
and self
in UIView1
:
init() {
self.label = UILabel()
label.text = "Hello, World!"
label.numberOfLines = 0
super.init(frame: .zero)
addSubview(label)
label.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
label.topAnchor.constraint(equalTo: topAnchor),
label.bottomAnchor.constraint(equalTo: bottomAnchor),
label.leftAnchor.constraint(equalTo: leftAnchor),
label.rightAnchor.constraint(equalTo: rightAnchor),
])
}