Reputation: 512
I need to have a long text that detects automatically the links in it, and if so, they would be clickable and in other color. I've succeed to do that. However, I have a problem going back to the line, this code returns all the text in one single line. I've tried adding "\n", fixedSize, layoutPriority but none of those worked.
struct RichTextView: UIViewRepresentable {
var text: String
func makeUIView(context: Context) -> UITextView {
let textView = UITextView()
textView.backgroundColor = .clear
textView.isEditable = false
textView.isScrollEnabled = false
textView.font = UIFont.systemFont(ofSize: 18)
textView.dataDetectorTypes = .all
textView.linkTextAttributes = [NSAttributedString.Key.foregroundColor: Colors.colorPrimary()]
textView.translatesAutoresizingMaskIntoConstraints = false
textView.textContainer.lineBreakMode = .byWordWrapping
textView.textContainer.widthTracksTextView = true
return textView
}
func updateUIView(_ uiView: UITextView, context: Context) {
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineSpacing = 5 // Set line spacing
paragraphStyle.paragraphSpacing = 10 // Set paragraph spacing
paragraphStyle.lineBreakMode = .byWordWrapping
paragraphStyle.lineBreakStrategy = NSParagraphStyle.LineBreakStrategy()
let attributedString = NSAttributedString(
string: text,
attributes: [
.font: UIFont.systemFont(ofSize: 18),
.paragraphStyle: paragraphStyle
]
)
uiView.attributedText = attributedString
uiView.sizeToFit()
uiView.isScrollEnabled = false
}}
So this is my custom view that detects links , and this is how I call it
RichTextView(text: description)
.frame(width: UIScreen.screenWidth, height: viewHeight)
.padding([.leading, .trailing])
.padding(.bottom, 16)
.multilineTextAlignment(.leading)
.lineLimit(nil)
.layoutPriority(1)
.lineSpacing(8)
.fixedSize(horizontal: false, vertical: false)
.onAppear {
self.viewHeight = calculateHeight(for: description, width: .infinity)
}
.onChange(of: description) { _ in
self.viewHeight = calculateHeight(for: description, width: .infinity)
}
I'm not sure that calculatedHeight is relevant but I'm going to put it anyways.
private func calculateHeight(for text: String, width: CGFloat) -> CGFloat {
let textView = UITextView()
textView.text = text
textView.font = UIFont.systemFont(ofSize: 18) // Use default system font with size 18
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineSpacing = 5 // Set line spacing
paragraphStyle.paragraphSpacing = 10 // Set paragraph spacing
let attributedString = NSAttributedString(
string: text,
attributes: [
.font: UIFont.systemFont(ofSize: 18),
.paragraphStyle: paragraphStyle
]
)
textView.attributedText = attributedString
textView.textContainer.lineBreakMode = .byWordWrapping
textView.textContainer.widthTracksTextView = true
textView.translatesAutoresizingMaskIntoConstraints = false
textView.textContainer.maximumNumberOfLines = 0
let size = textView.sizeThatFits(CGSize(width: width, height: CGFloat.greatestFiniteMagnitude))
return size.height}
Upvotes: 0
Views: 71