9

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?

pawello2222
  • 34,912
  • 15
  • 99
  • 151
Mojtaba Hosseini
  • 71,072
  • 19
  • 226
  • 225

2 Answers2

27

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

Mojtaba Hosseini
  • 71,072
  • 19
  • 226
  • 225
  • 2
    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. – ngb Jan 08 '21 at 08:29
  • Also it doesn't work in editMode. I had to fake it by creating the + and - circles – ngb Jan 08 '21 at 08:32
  • 1
    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. – Clifton Labrum Mar 05 '21 at 22:00
8

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

Asperi
  • 173,274
  • 14
  • 284
  • 455