Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamic row hight containing TextEditor inside a List in SwiftUI

Tags:

swift

swiftui

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?

like image 205
Mojtaba Hosseini Avatar asked Jun 28 '20 09:06

Mojtaba Hosseini


2 Answers

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

like image 149
Mojtaba Hosseini Avatar answered Oct 28 '22 16:10

Mojtaba Hosseini


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

like image 8
Asperi Avatar answered Oct 28 '22 16:10

Asperi