You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ScrollView中UIViewRepresentable封装的UITextView渲染异常求助

问题:SwiftUI封装UITextView无法自适应高度完整显示文本

在SwiftUI中封装UITextView用于渲染内容时,出现文本被截断或超出屏幕的问题:当前代码里的UITextView要么只显示第一行后截断,要么移除content相关设置后内容超出屏幕范围,无法像SwiftUI原生Text组件那样自适应高度完整显示。

复现代码

struct ContentView: View {
    var body: some View {
        ScrollView {
                Text(text)
                WrappedUITextView(text)
        }.padding()

    }
}

struct WrappedUITextView: UIViewRepresentable {
    private let textContent: String

    init(_ textContent: String) {
        self.textContent = textContent
    }

    func makeUIView(context: Context) -> UITextView {

        let uiTextView = UITextView()

        uiTextView.backgroundColor = .clear

        uiTextView.isEditable = false
        uiTextView.isScrollEnabled = false
        uiTextView.setContentHuggingPriority(.defaultLow, for: .vertical)
        uiTextView.setContentHuggingPriority(.defaultLow, for: .horizontal)
        uiTextView.setContentCompressionResistancePriority(.required, for: .vertical)
        uiTextView.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)

        return uiTextView
    }

    func updateUIView(_ uiTextView: UITextView, context: Context) {
        uiTextView.text = textContent
    }
}

let text = """
            Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.
            """

当前渲染效果

UITextView文本截断效果


解决办法

核心问题是UITextView的自动布局优先级设置错误,导致SwiftUI无法正确识别它的自适应高度需求,调整以下两点即可解决:

  • 修正垂直方向的内容拥抱优先级
    将UITextView的垂直内容拥抱优先级设为defaultHigh,告诉SwiftUI优先让视图适应自身内容高度,而非被父视图压缩:

    uiTextView.setContentHuggingPriority(.defaultHigh, for: .vertical)
    
  • 确保文本更新后重新计算视图尺寸
    在updateUIView方法中设置文本后,调用sizeToFit()和layoutIfNeeded(),让UITextView重新计算自身的固有尺寸,确保SwiftUI能获取到正确的高度:

    func updateUIView(_ uiTextView: UITextView, context: Context) {
        uiTextView.text = textContent
        uiTextView.sizeToFit()
        uiTextView.layoutIfNeeded()
    }
    

修改后的完整WrappedUITextView代码

struct WrappedUITextView: UIViewRepresentable {
    private let textContent: String

    init(_ textContent: String) {
        self.textContent = textContent
    }

    func makeUIView(context: Context) -> UITextView {
        let uiTextView = UITextView()
        uiTextView.backgroundColor = .clear
        uiTextView.isEditable = false
        uiTextView.isScrollEnabled = false
        
        // 修正垂直方向优先级,确保自适应高度
        uiTextView.setContentHuggingPriority(.defaultHigh, for: .vertical)
        uiTextView.setContentHuggingPriority(.defaultLow, for: .horizontal)
        uiTextView.setContentCompressionResistancePriority(.required, for: .vertical)
        uiTextView.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
        
        return uiTextView
    }

    func updateUIView(_ uiTextView: UITextView, context: Context) {
        uiTextView.text = textContent
        // 强制重新计算尺寸
        uiTextView.sizeToFit()
        uiTextView.layoutIfNeeded()
    }
}

修改后,封装的UITextView就能像SwiftUI原生Text组件一样,自适应内容高度并完整显示全部文本。


内容的提问来源于stack exchange,提问作者Nico

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 15:41:26