16

I have a List containing a TextEditor

struct ContentView: View {
    @State var text: String = "test"

    var body: some View {
        List((1...10), id: \.self) { _ in
            TextEditor(text: $text)
        }
    }
}

But it's items are not growing on height change of the TextEditor. I have tried .fixedSize() modifier with no luck. What am I missing here?

2 Answers 2

36

iOS 13

You can use an invisible Text in a ZStack to make it dynamic.

struct ContentView: View {
    @State var text: String = "test"

    var body: some View {
        List((1...10), id: \.self) { _ in
            ZStack {
                TextEditor(text: $text)
                Text(text).opacity(0).padding(.all, 8) // <- This will solve the issue if it is in the same ZStack
            }
        }
    }
}

Note that you should consider changing font size and other properties to match the TextEditor

Preview


iOS 16

If you are just looking for a vertical growing input field, there is a parameter called axis in TextField that causes the field to grow vertically if needed:

TextField("", text: $text, axis: .vertical)

Note that if you test with the mac keyboard, you need to hold option for new lines.


Sign up to request clarification or add additional context in comments.

3 Comments

I had to put the Text label before the TextEditor in the ZStack. Also to ensure the scrollbar doesn't come up I had to put the ZStack inside a HStack.
Also it doesn't work in editMode. I had to fake it by creating the + and - circles
While implementing this approach In iOS 14.4, the TextEditor has a scrollbar initially and only one line of text is shown. If I edit the text, the list row expands to fit the content and the TextEditor's scrollbar disappears. It seems pretty buggy.
10

As far as I can see from view hierarchy TextEditor is just simple wrapper around UITextView and does not have more to add, so you can huck into that layer and find UIKit solution for what you need, or ...

here is a demo of possible approach to handle it at SwiftUI level (the idea is to use Text view as a reference for wrapping behaviour and adjust TextEditor exactly to it)

Tested with Xcode 12b / iOS 14 (red border is added for better visibility)

demo

Modified your view:

struct ContentView: View {
    @State var text: String = "test"

    @State private var height: CGFloat = .zero
    var body: some View {
        List {
            ForEach((1...10), id: \.self) { _ in
                ZStack(alignment: .leading) {
                    Text(text).foregroundColor(.clear).padding(6)
                        .background(GeometryReader {
                            Color.clear.preference(key: ViewHeightKey.self, value: $0.frame(in: .local).size.height)
                        })
                    TextEditor(text: $text)
                        .frame(minHeight: height)
                        //.border(Color.red)        // << for testing
                }
                .onPreferenceChange(ViewHeightKey.self) { height = $0 }
            }
        }
    }
}

Note: ViewHeightKey is a preference key, used in my other solutions, so can be get from there

ForEach and GeometryReader: variable height for children?

How to make a SwiftUI List scroll automatically?

Automatically adjustable view height based on text height in SwiftUI

4 Comments

This approach works great in a List, but doesn't seem to work in a ScrollView with a VStack. Have you ever tried it that way by chance?
You can use .fixedSize(horizontal: false, vertical: true) if you aren't using List.
@TarekHallak Great tip on this! We needed this to make it work. For anybody needing this too, we put the .fixedSize on the Text, not the TextEditor. Why does this work, though?
Unfortunaltely, the height of the TextEditor is not the same as Text. One need to ad like 10 to disable internal scroll of TextEditor. This may not be seen in a few lines, though!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.