UITextView嵌套ScrollView时文本截断的SwiftUI技术问题
SwiftUI中ScrollView嵌套UITextView内容截断问题解决
问题现象
- 在普通
VStack中,文本可完整显示 - 放入
ScrollView后,文本较多时会被截断:UITextView布局尺寸正常(分隔线位置验证),但内容无法完全展示 - 显式设置
frame可解决内容截断,但需创建Binding,导致LazyVStack内的ScrollView出现抖动
原代码
SwiftUI主视图
var body: some View { VStack { TextView(text: text) Rectangle().frame(height: 1).foregroundStyle(.red) ScrollView { TextView(text: text) Rectangle().frame(height: 1).foregroundStyle(.red) } } .padding(.horizontal) }
UITextView封装视图
struct TextView: UIViewRepresentable { let text: String func makeUIView(context: Context) -> UITextView { let textView = UITextView() textView.text = text textView.setContentCompressionResistancePriority(.defaultLow, for: .horizontal) textView.isUserInteractionEnabled = true textView.isSelectable = true textView.isEditable = false textView.isScrollEnabled = false textView.backgroundColor = .clear textView.textContainer.lineFragmentPadding = 0 textView.textContainerInset = .zero return textView } func updateUIView(_ textView: UITextView, context: Context) { } }
解决方案
问题核心是ScrollView内部的UITextView未正确向SwiftUI报告自身内容高度,导致内容显示被截断。修改TextView代码,确保其正确计算并返回固有内容尺寸:
struct TextView: UIViewRepresentable { let text: String func makeUIView(context: Context) -> UITextView { let textView = UITextView() // 禁用自动布局转换,让SwiftUI管理约束 textView.translatesAutoresizingMaskIntoConstraints = false textView.text = text textView.isUserInteractionEnabled = true textView.isSelectable = true textView.isEditable = false // 必须禁用滚动,让UITextView根据内容计算高度 textView.isScrollEnabled = false textView.backgroundColor = .clear textView.textContainer.lineFragmentPadding = 0 textView.textContainerInset = .zero // 设置垂直内容拥抱优先级,避免被压缩 textView.setContentHuggingPriority(.defaultHigh, for: .vertical) return textView } func updateUIView(_ textView: UITextView, context: Context) { // 仅当文本变化时更新,避免不必要的刷新 if textView.text != text { textView.text = text // 强制布局,确保固有尺寸更新 textView.layoutIfNeeded() } } }
关键修改点说明
- 添加
textView.translatesAutoresizingMaskIntoConstraints = false:让SwiftUI完全控制UITextView的布局约束,避免自动布局冲突 - 设置垂直内容拥抱优先级为
.defaultHigh:确保UITextView在ScrollView中不会被垂直方向压缩 - 在
updateUIView中更新文本后调用layoutIfNeeded():强制UITextView重新计算内容尺寸,确保固有内容高度正确传递给SwiftUI
这样修改后,ScrollView中的UITextView能完整展示全部文本,无需额外Binding,也不会导致LazyVStack内的抖动问题。
内容的提问来源于stack exchange,提问作者Khaled Sh
相关产品推荐
相关产品推荐

