【问题标题】:Controlling size of TextEditor in SwiftUI在 SwiftUI 中控制 TextEditor 的大小
【发布时间】:2021-08-31 17:15:10
【问题描述】:

我想在我的 ForEach 中有一些 TextEditor,我把这个示例代码写下来了!正如您在 Image 中看到的代码和结果,TextEditor 就像一个贪婪的视图,并占用所有可用空间!至少对我来说有很多缺点!

如果我将高度限制为自定义值,那么我将失去查看 TextEditor 本身的所有字符串和字符串行的可能性,我必须向上或向下滚动才能看到其他行,这不是我的设计!

我的目标是TextEditor 根据需要占用空间,如果我输入新的字符串行,那么它可以增加高度,或者如果我删除字符串行,它的高度可以缩小到至少 1 行最少!

我想知道我该怎么做?

struct ContentView: View {
    
    @StateObject var textEditorReferenceType: TextEditorReferenceType = TextEditorReferenceType()
    
    var body: some View {
        
        Text("TextEditorView").bold().padding()
        
        VStack {
            
            ForEach(textEditorReferenceType.arrayOfString.indices, id: \.self, content: { index in
                
                TextEditorView(string: $textEditorReferenceType.arrayOfString[index])

            })
            
        }
        .padding()
        
    }
}


struct TextEditorView: View {
    
    @Binding var string: String
    
    var body: some View {
        
        TextEditor(text: $string)
            .cornerRadius(10.0)
            .shadow(radius: 1.0)
        
    }
    
}

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

当前代码结果:

我的目标结果:

【问题讨论】:

标签: swift swiftui


【解决方案1】:

您可以使用PreferenceKey 和不可见的Text 覆盖来测量字符串尺寸并设置TextEditor 的框架:


struct TextEditorView: View {
    
    @Binding var string: String
    @State var textEditorHeight : CGFloat = 20
    
    var body: some View {
        
        ZStack(alignment: .leading) {
            Text(string)
                .font(.system(.body))
                .foregroundColor(.clear)
                .padding(14)
                .background(GeometryReader {
                    Color.clear.preference(key: ViewHeightKey.self,
                                           value: $0.frame(in: .local).size.height)
                })
            
            TextEditor(text: $string)
                .font(.system(.body))
                .frame(height: max(40,textEditorHeight))
                .cornerRadius(10.0)
                            .shadow(radius: 1.0)
        }.onPreferenceChange(ViewHeightKey.self) { textEditorHeight = $0 }
        
    }
    
}


struct ViewHeightKey: PreferenceKey {
    static var defaultValue: CGFloat { 0 }
    static func reduce(value: inout Value, nextValue: () -> Value) {
        value = value + nextValue()
    }
}

改编自我的其他答案:Mimicking behavior of iMessage with TextEditor for text entry

【讨论】:

  • 谢谢,它很好用,我想知道 TextEditor 是否为我们提供了这个选项?
  • 不——这就是为什么我们必须使用这样的解决方案。