使用“UIViewRepresentable”桥接一个“UITextView”,该视图可以根据SwiftUI的文本进行缩放

使用“UIViewRepresentable”桥接一个“UITextView”,该视图可以根据SwiftUI的文本进行缩放,swiftui,uitextview,uiviewrepresentable,Swiftui,Uitextview,Uiviewrepresentable,如果我想要一个非滚动的UITextView,它占据整个宽度,并垂直伸缩以适应其文本,我可以在UIKit中这样做: import UIKit class TestViewController: UIViewController { private lazy var textView = UITextView() override func viewDidLoad() { super.viewDidLoad() guard let view =

如果我想要一个非滚动的
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)
    }
}
看起来是这样的:

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()
        }
    }
}

我想通过使用
uiviewsrepresentable
包装
UITextView
将其连接到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
        }
    }
}
设置
textView.setContentCompressionResistancePriority(.defaultLow,for:.horizontal)
成功地使文本视图将其文本包装到多行,但高度填充整个屏幕:

添加
textView.setContentHuggingPriority(.defaultHigh,for:.vertical)
会缩小高度,但现在换行不再有效;所有文本都在框架外的一行中:


我在文档或在线中没有找到太多关于
UIViewRepresentable
如何将布局从UIKit连接到SwiftUI的内容。有没有办法实现这种自动增长和收缩以适应行为?或者我必须用
sizeThatFits
做一些黑客的事情,并在文本发生变化时手动设置框架?

这个主题应该会很有帮助。感谢@Asperi的链接,我希望有一种方法可以不用手动计算框架,但很高兴知道这至少是可能的!这个主题应该很有帮助。感谢@Asperi的链接,我希望有一种不用手动计算框架的方法,但很高兴知道至少这种方法是可行的!