需要在SwiftUI的表视图中显示html格式的文本,但是Text(“ Hi”)不允许我们在其中使用属性文本。
因此,尝试使用以下代码在List中显示多行HTML格式的文本。但是没有成功。
并且单元格的高度应根据内容大小的高度动态变化。
struct ContentView: View {
@State var text = "Hello World This is line with more than two line of code to display as multiline textview inside the List cell."
@State var bool: Bool = false
var body: some View {
List(0 ..< 5) { item in
TextView(text: self.$text)
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
}
}
}
struct TextView: UIViewRepresentable {
@Binding var text: String
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
func makeUIView(context: Context) -> UITextView {
let myTextView = UITextView()
myTextView.delegate = context.coordinator
myTextView.font = UIFont(name: "HelveticaNeue", size: 15)
myTextView.isScrollEnabled = false
myTextView.isEditable = false
myTextView.isUserInteractionEnabled = true
myTextView.backgroundColor = .clear //UIColor(white: 0.0, alpha: 0.05)
myTextView.translatesAutoresizingMaskIntoConstraints = false
myTextView.isScrollEnabled = false
return myTextView
}
func updateUIView(_ uiView: UITextView, context: Context) {
uiView.text = text
}
class Coordinator : NSObject, UITextViewDelegate {
var parent: TextView
init(_ uiTextView: TextView) {
self.parent = uiTextView
}
// with delegate methods implemented normally
}
}
答案 0 :(得分:0)
如何执行此操作:
myTextView.isScrollEnabled = true
这项工作吗?
答案 1 :(得分:0)
尝试以下代码,希望对您有所帮助。
(如果需要任何更正,请发表评论)
struct ContentView: View {
let text = "<p>This is<br>a paragraph<br>with line breaks. This is <sup>superscripted</sup> text.</p>"
@State var bool: Bool = false
var body: some View {
List(0..<5) { item in
Text(self.text.htmlToAttributedString.string)
.font(Font.system(size: 17))
.multilineTextAlignment(.leading)
}
}
}
扩展
extension String {
var htmlToAttributedString: NSAttributedString {
guard let data = data(using: .utf8) else { return NSAttributedString() }
do {
return try NSAttributedString(data: data, options: [.documentType: NSAttributedString.DocumentType.html, .characterEncoding: String.Encoding.utf8.rawValue], documentAttributes: nil)
} catch {
return NSAttributedString()
}
}
}
输出
答案 2 :(得分:0)
暂时无法获得主链接,我从那里获得了该链接,但它可以根据需要工作。
ScrollView {
VStack {
ForEach(/*your implementation*/) { item in
UITextViewWrapper(text: self.$text, calculatedHeight: self.$size, onDone: nil)
}
.frame(minWidth: 0, maxWidth: proxy.size.width, minHeight: self.size, maxHeight: .infinity)
}
}
fileprivate struct UITextViewWrapper: UIViewRepresentable {
typealias UIViewType = UITextView
@Binding var text: String
@Binding var calculatedHeight: CGFloat
var onDone: (() -> Void)?
func makeUIView(context: UIViewRepresentableContext<UITextViewWrapper>) -> UITextView {
let textField = UITextView()
textField.delegate = context.coordinator
textField.isEditable = false
textField.font = UIFont.preferredFont(forTextStyle: .body)
textField.isSelectable = false
textField.isUserInteractionEnabled = false
textField.isScrollEnabled = true
textField.backgroundColor = UIColor.clear
if nil != onDone {
textField.returnKeyType = .done
}
// textField.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
return textField
}
func updateUIView(_ uiView: UITextView, context: UIViewRepresentableContext<UITextViewWrapper>) {
if uiView.text != self.text {
uiView.text = self.text
}
if uiView.window != nil, !uiView.isFirstResponder {
uiView.becomeFirstResponder()
}
UITextViewWrapper.recalculateHeight(view: uiView, result: $calculatedHeight)
}
fileprivate static func recalculateHeight(view: UIView, result: Binding<CGFloat>)
{
let newSize = view.sizeThatFits(CGSize(width: view.frame.size.width, height: CGFloat.greatestFiniteMagnitude))
if result.wrappedValue != newSize.height
{
DispatchQueue.main.async
{
result.wrappedValue = newSize.height // !! must be called asynchronously
}
}
}
func makeCoordinator() -> Coordinator {
return Coordinator(text: $text, height: $calculatedHeight, onDone: onDone)
// return Coordinator()
}
final class Coordinator: NSObject, UITextViewDelegate {
var text: Binding<String>
var calculatedHeight: Binding<CGFloat>
var onDone: (() -> Void)?
init(text: Binding<String>, height: Binding<CGFloat>, onDone: (() -> Void)? = nil) {
self.text = text
self.calculatedHeight = height
self.onDone = onDone
}
func textViewDidChange(_ uiView: UITextView) {
text.wrappedValue = uiView.text
UITextViewWrapper.recalculateHeight(view: uiView, result: calculatedHeight)
}
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
if let onDone = self.onDone, text == "\n" {
textView.resignFirstResponder()
onDone()
return false
}
return true
}
}
}