【发布时间】:2021-06-16 20:43:43
【问题描述】:
我正在构建一个 SwiftUI 应用程序,我想将一个可编辑的 UITextView(包装在 UIViewRepresentable 中)放入一个 SwiftUI ScrollView。这样做的原因是我想将其他 SwiftUI 内容放在文本上方,并且我希望它与文本一起滚动。我需要一个 TextView,因为我想要富文本和工具栏。
我以为我可以禁用 UITextView 上的滚动并赋予它无限的高度,但这也赋予它无限的宽度,因此屏幕边缘的文本水平滚动,直到添加换行符。我已尝试按照How to disable vertical scrolling in UITextView? 等帖子中的建议将 textview 的内容大小和框架大小设置为屏幕宽度,但我无法使其工作。我可以成功更新 textview 内容大小,但更改似乎稍后会被覆盖(请参阅 textViewDidChange 中的打印语句)。
有什么方法可以实现吗?即 SwiftUI ScrollView 中的可编辑 UITextView。提前致谢!
import SwiftUI
struct TextView: UIViewRepresentable {
var attributedString: NSAttributedString
var fixedWidth: CGFloat
func makeCoordinator() -> Coordinator {
return Coordinator(self)
}
class Coordinator: NSObject, UITextViewDelegate {
var parent: TextView
init(_ parent: TextView) {
self.parent = parent
}
func textViewDidChange(_ textView: UITextView) {
print("pre content size update: \(textView.contentSize)") // width is over limit
let newSize = textView.sizeThatFits(CGSize(width: parent.fixedWidth, height: CGFloat.greatestFiniteMagnitude))
textView.contentSize = CGSize(width: max(newSize.width, parent.fixedWidth), height: newSize.height)
print("post content size update: \(textView.contentSize)") // width is updated
}
}
func makeUIView(context: Context) -> UITextView {
let textView = UITextView(frame: .zero)
textView.isEditable = true
textView.isScrollEnabled = false
textView.backgroundColor = .cyan // just to make it easier to see
textView.delegate = context.coordinator
return textView
}
func updateUIView(_ textView: UITextView, context: Context) {
textView.attributedText = self.attributedString
}
}
struct ContentView: View {
var body: some View {
GeometryReader { geo in
ScrollView(.vertical) {
VStack(alignment: .leading, spacing: /*@START_MENU_TOKEN@*/nil/*@END_MENU_TOKEN@*/){
//Other content
Image(systemName: "photo")
.font(.largeTitle)
Button("A button"){
print("i'm a button")
}
//Editable textview
TextView(attributedString: NSAttributedString(string: "Here is a long string as you can see it is not wrapping but instead scrolling off the edge of the screen"), fixedWidth: geo.size.width)
.frame(width: geo.size.width)
.frame(maxHeight: .infinity)
}
.padding(.horizontal)
}
}
}
}
我尝试过的其他一些事情:
- 仅使用普通的可滚动文本视图并将我的所有内容作为文本附件放入 NSAttributed 字符串中 -> 对我的内容而言过于严格并且难以检测到用户交互
- 在 updateUIView() 中为 textview 设置锚约束 -> 当文本为空时效果很好,但如果屏幕已经加载了文本,那么父视图的布局将完全重新排列
- 像How to use an NSAttributedString with a ScrollView in SwiftUI? -> 那样将一个绑定从父级传递到textview 的高度和宽度是行不通的。我认为问题不像最初出现的那样相似 - 我想为可编辑文本设置固定大小,而这个问题想要为不可编辑文本设置可调整的内容大小
【问题讨论】:
-
你好有什么解决办法吗?
-
对不起,我从来没有想到这一点。最后,我进行了设置,以便在编辑 uitextview 时进入“全屏”状态 - 当键盘出现时,它上面的其他 swiftui 内容就会消失。这样我就不必处理与 uitextview 一起滚动的 swiftui 内容。它是一种解决方法,但它看起来像一个功能
标签: ios swift swiftui uiscrollview uitextview