如果我想要一个非滚动的UITextView
,它可以采用整个宽度,并且可以垂直扩展和缩小以适合其文本,那么我可以在UIKit中这样做:
import UIKit
class TestViewController: UIViewController {
private lazy var textView = UITextView()
override func viewDidLoad() {
super.viewDidLoad()
guard let view = view else { return }
view.backgroundColor = .white
textView.text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
textView.backgroundColor = .systemYellow
textView.isEditable = true
textView.isSelectable = true
textView.isScrollEnabled = false // We want the view to resize to fit text instead of scrolling
view.addSubview(textView)
textView.translatesAutoresizingMaskIntoConstraints = false
let constraints = [
textView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
textView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor),
textView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor)
]
NSLayoutConstraint.activate(constraints)
}
}
它看起来像这样:
我想通过用UITextView
包装UIViewRepresentable
来将它桥接到SwiftUI。我是这样做的,其文本视图的配置与UIKit示例中的设置完全相同:
import SwiftUI
import UIKit
struct TextView: UIViewRepresentable {
@Binding var text: String
func makeUIView(context: Context) -> UITextView {
let textView = UITextView()
textView.delegate = context.coordinator
textView.backgroundColor = .clear
textView.isEditable = true
textView.isSelectable = true
textView.isScrollEnabled = false // We want the view to resize to fit text instead of scrolling
// Makes the text wrap rather than extend on one line outside the parent frame
textView.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
return textView
}
func makeCoordinator() -> Coordinator {
return Coordinator(text: _text)
}
func updateUIView(_ uiView: UITextView, context: Context) {
uiView.text = text
}
}
extension TextView {
class Coordinator: NSObject, UITextViewDelegate {
@Binding var text: String
init(text: Binding<String>) {
self._text = text
}
func textViewDidChange(_ textView: UITextView) {
self.text = textView.text
}
}
}
并在SwiftUI中像这样使用它:
import SwiftUI
struct ContentView: View {
@State var text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
var body: some View {
VStack(alignment: .leading) {
TextView(text: $text)
.background(Color.yellow)
Spacer()
}
}
}
成功设置textView.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
可以使文本视图将其文本包装到多行中,但是高度会填满整个屏幕:
添加textView.setContentHuggingPriority(.defaultHigh, for: .vertical)
确实会缩小高度,但是现在换行不再有效;所有文本都在框架外的一行中:
我没有在文档或在线中找到太多有关UIViewRepresentable
如何将布局从UIKit桥接到SwiftUI的信息。有什么方法可以实现这种自动增长和收缩以适应行为?还是我需要对sizeThatFits
做一些骇人听闻的工作,并在每次文本更改时手动设置框架?