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

SwiftUI中如何实现TextEditor高度随内容动态自适应调整

实现方案

核心思路是通过隐藏的同步文本计算内容实际高度,动态绑定给TextEditor,同时限制最小高度保证至少显示1行内容,完整可运行代码如下:

import SwiftUI

// 用于传递视图高度的PreferenceKey
struct ViewHeightKey: PreferenceKey {
    static var defaultValue: CGFloat = 0
    static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) {
        value = nextValue()
    }
}

struct ContentView: View {
    @StateObject var textEditorReferenceType: TextEditorReferenceType = TextEditorReferenceType()
    var body: some View {
        Text("TextEditorView").bold().padding()
        VStack(spacing: 15) {
            ForEach($textEditorReferenceType.arrayOfString, id: \.self) { $string in
                TextEditorView(string: $string)
            }
        }
        .padding()
    }
}

struct TextEditorView: View {
    @Binding var string: String
    // 存储文本内容的实际高度
    @State private var textHeight: CGFloat = 0
    // 最小高度,可容纳1行文本,可根据需求调整
    private let minHeight: CGFloat = 38
    // 可选:设置最大高度,超过后内容变为滚动状态,不需要可删除该参数
    private let maxHeight: CGFloat = 150
    
    var body: some View {
        TextEditor(text: $string)
            .frame(minHeight: minHeight, maxHeight: max(maxHeight, textHeight))
            .fixedSize(horizontal: false, vertical: true)
            .cornerRadius(10.0)
            .shadow(radius: 1.0)
            .background(
                // 用和TextEditor同配置的隐藏Text计算内容实际高度
                Text(string)
                    .font(.body) // 需和TextEditor的字体保持完全一致
                    .foregroundColor(.clear)
                    .padding(4) // 对齐TextEditor的默认内边距,可根据实际样式调整
                    .frame(maxWidth: .infinity, alignment: .leading)
                    .getViewHeight($textHeight)
            )
    }
}

// 扩展View,添加读取高度的便捷方法
extension View {
    func getViewHeight(_ binding: Binding<CGFloat>) -> some View {
        self.background(
            GeometryReader { geo in
                Color.clear.preference(key: ViewHeightKey.self, value: geo.size.height)
            }
        )
        .onPreferenceChange(ViewHeightKey.self) { value in
            binding.wrappedValue = value
        }
    }
}

class TextEditorReferenceType: ObservableObject {
    @Published var arrayOfString: [String] = ["Hello, World!", "Hello, World!", "Hello, World!"]
}

实现说明

  1. 隐藏Text和TextEditor绑定同一份文本、使用相同字体配置,它的高度始终等于文本内容实际所需的高度
  2. 通过PreferenceKey将隐藏Text的高度同步给TextEditor的frame,实现高度随内容自适应
  3. minHeight参数保证TextEditor至少可以显示一行内容,maxHeight为可选配置,避免文本过多时控件占满整屏
  4. 如果自定义了TextEditor的字体、内边距,需要同步修改隐藏Text的对应配置,保证高度计算准确

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 22:06:03