swiftui - 使用 `UIViewRepresentable` 来桥接 `UITextView`,它会增长和缩小以使其文本适合 SwiftUI
问题描述
如果我想要一个占据整个宽度并垂直增长和收缩以适应其文本的非滚动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
. 我是这样做的,文本视图的配置与 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
在文本更改时手动设置框架?
解决方案
推荐阅读
- sql - SQL 连接具有相同列名的两个表
- discord.js - 如何制作队列系统 - Discord.js
- typescript - 在 Expo 和 TypeScript 中的类型“{}”上不存在属性“origin”
- javascript - 为什么Javascript中原型继承的嵌套级别总是1?
- android - 错误配置流发布允许失败 | rtmp-rtsp-stream-client-java 库为android | Youtube 直播 api
- google-chrome-devtools - PuppeteerSharp:如何同时启用请求拦截和缓存?
- c - 如何使用 Arb 库获得更高的正弦精度?
- python-3.x - 在 if/else 语句中使用方括号对函数的参数有什么作用?
- matlab - 在 Matlab 中的另一个矩阵中查找矩阵的行成员
- magento2 - magento 1 到 magento 2 问题迁移