Search code examples
stringtextdynamicswiftuiheight

Make TextEditor dynamic height SwiftUI


I'm trying to create a growing TextEditor as input for a chat view.

The goal is to have a box which expands until 6 lines are reached for example. After that it should be scrollable.

I already managed to do this with strings, which contain line breaks \n.

                        TextEditor(text: $composedMessage)
                            .onChange(of: self.composedMessage, perform: { value in
                                withAnimation(.easeInOut(duration: 0.1), {
                                    if (value.numberOfLines() < 6) {
                                        height = startHeight + CGFloat((value.numberOfLines() * 20))
                                    }
                                    if value.numberOfLines() == 0 || value.isEmpty {
                                        height = 50
                                    }
                                })
                            })

I created a string extension which returns the number of line breaks by calling string.numberOfLines() var startHeight: CGFloat = 50

The problem: If I paste a text which contains a really long text, it's not expanding when this string has no line breaks. The text get's broken in the TextEditor.

How can I count the number of breaks the TextEditor makes and put a new line character at that position?


Solution

  • I found a solution!

    For everyone else trying to solve this:

    I added a Text with the same width of the input field and then used a GeometryReader to calculate the height of the Text which automatically wraps. Then if you divide the height by the font size you get the number of lines.

    You can make the text field hidden (tested in iOS 14 and iOS 15 beta 3)