Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Controlling size of TextEditor in SwiftUI

Tags:

swift

swiftui

I wanted to have some TextEditor in my ForEach and I made this sample code in down! As you can see the code and result of it in Image, TextEditor act like a greedy view, and takes all available space! which has so many downsides for me at least!

If I go and limit the hight to a custom value then I would loss the possibility of seeing all strings and lines of strings of TextEditor in itself and I must scroll up or down for seeing other lines, which is not my design!

My goal is that the TextEditor takes the space as it needs and if I enter new line of string then it can grow in height or if I remove the lines of strings it can shrinks in height to minimum of 1 line at least!

I wonder how can I do this?

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!"]
    
}

Result of current code:

enter image description here

Result of my Goal:

enter image description here

like image 630
ios coder Avatar asked Sep 10 '25 02:09

ios coder


2 Answers

iOS 16 - Native SwiftUI

In iOS 16 it's now natively possible with a regular textField by adding axis: .vertical and .lineLimit()

linelimit defines the number of lines until the textfield extends. Add a range to start to define a range of lines within the textfield will start and stop to extend.

enter image description here

WWDC22 Session "What'S new in SwiftUI around 17:10

like image 112
wildcard Avatar answered Sep 14 '25 19:09

wildcard


You can use a PreferenceKey and an invisible Text overlay to measure the string dimensions and set the TextEditor's frame:


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

Adapted from my other answer here: Mimicking behavior of iMessage with TextEditor for text entry

like image 29
jnpdx Avatar answered Sep 14 '25 19:09

jnpdx