Reputation: 2882
I'm trying to integrate a UITextView
inside a SwiftUI view (in order to render HTML content, similar to what's done here: Frame height problem with custom UIViewRepresentable UITextView in SwiftUI).
I can't get a sane behavior for the wrapped UITextView
, text is either cut after 1st line or extended beyond the screen (if setContent*
are omitted).
Here is a minimal code to reproduce the issue:
struct ContentView: View {
var body: some View {
ScrollView {
Text(text)
WrappedUITextView(text)
}.padding()
}
}
struct WrappedUITextView: UIViewRepresentable {
private let textContent: String
init(_ textContent: String) {
self.textContent = textContent
}
func makeUIView(context: Context) -> UITextView {
let uiTextView = UITextView()
uiTextView.backgroundColor = .clear
uiTextView.isEditable = false
uiTextView.isScrollEnabled = false
uiTextView.setContentHuggingPriority(.defaultLow, for: .vertical)
uiTextView.setContentHuggingPriority(.defaultLow, for: .horizontal)
uiTextView.setContentCompressionResistancePriority(.required, for: .vertical)
uiTextView.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
return uiTextView
}
func updateUIView(_ uiTextView: UITextView, context: Context) {
uiTextView.text = textContent
}
}
let text = """
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.
"""
This code render to this screen:
Obviously the intended behavior is having the text displayed completely as with the Text()
SwiftUI Component.
Do you have any idea to improve this?
Upvotes: 1
Views: 989
Reputation: 2882
For iOS 16 and up, Patrick's response works great.
For iOS 14 and up, I had success with the RepresentableKit library
import SwiftUI
import RepresentableKit
struct ContentView: View {
var body: some View {
ScrollView {
Text(text)
UIViewAdaptor {
let uiTextView = UITextView()
uiTextView.text = text
uiTextView.isEditable = false
uiTextView.isScrollEnabled = false
uiTextView.setContentHuggingPriority(.defaultLow, for: .vertical)
uiTextView.setContentHuggingPriority(.defaultLow, for: .horizontal)
uiTextView.setContentCompressionResistancePriority(.required, for: .vertical)
uiTextView.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
return uiTextView
}
}.padding()
}
}
Upvotes: 0
Reputation: 458
I faced the same problem, from iOS 16 and up, UIViewRepresentable
has a new method sizeThatFits(_:uiView:context:) -> CGSize?
that helps with this.
I implemented it as follows:
func sizeThatFits(_ proposal: ProposedViewSize, uiView: DropCapView, context: Context) -> CGSize? {
let size = uiView.systemLayoutSizeFitting(
CGSize(
width: proposal.width ?? UIView.layoutFittingCompressedSize.width,
height: UIView.layoutFittingCompressedSize.height
),
withHorizontalFittingPriority: .required,
verticalFittingPriority: .defaultLow
)
return proposal.replacingUnspecifiedDimensions(by: size)
}
Upvotes: 4