0

So I have made a successful dynamic TextEditor but when I try to combine views, it overlaps the other elements and no longer expands as you type. I am pretty sure this has to do with Geometry Reader but I am not sure how to do it without that. Thanks!

ScrollView {
    
    GeometryReader { geometry in
        
        
        VStack{
            
            
            ZStack(alignment: .leading) {
                
                Text(text).foregroundColor(.clear)
                .padding(14)
                .font(.custom("Times", size: 14))
                .background(GeometryReader {
                    Color.clear.preference(key: viewheightkey3.self, value: $0.frame(in: .local).size.height)
                })
                .frame(width: geometry.size.width * 0.9)
                
                TextEditor(text: $text)
                .padding(6)
                .foregroundColor(.white)
                .frame(width: geometry.size.width * 0.9)
                .frame(height: height)
                .frame(minHeight: 100)
                .background(Color.black)
                
            }
            
            .padding(20)
            .onPreferenceChange(viewheightkey3.self) { height = $0 }
            
        }
        
        
    }
    
    struct viewheightkey3: PreferenceKey {
        static var defaultValue: CGFloat { 0 }
        static func reduce(value: inout Value, nextValue: () -> Value) {
            value = value + nextValue()
        }
    }
aheze
  • 24,434
  • 8
  • 68
  • 125

1 Answers1

1

If you can stand to get rid of the frame width stuff (which you can probably substitute with just doing some horizontal padding), this seems to work:

struct ContentView: View {
    @State private var textEditorHeight : CGFloat = 100
    @State private var text = "Testing text. Hit a few returns to see what happens"
    
    var body: some View {
        ScrollView {
            VStack{
                Text("This should be above")
                ZStack(alignment: .leading) {
                    Text(text)
                        .font(.custom("Courier", size: 24))
                        .foregroundColor(.clear)
                        .padding(14)
                        .background(GeometryReader {
                            Color.clear.preference(key: ViewHeightKey.self,
                                                   value: $0.frame(in: .local).size.height)
                        })
                    
                    TextEditor(text: $text)
                        .font(.custom("Courier", size: 24))
                        .padding(6)
                        .frame(height: textEditorHeight)
                        .background(Color.black)
                }
                .padding(20)
                .onPreferenceChange(ViewHeightKey.self) { textEditorHeight = $0 }
                
                Text("This should be below the text field")
            }
        }
    }
}

struct ViewHeightKey: PreferenceKey {
    static var defaultValue: CGFloat { 0 }
    static func reduce(value: inout Value, nextValue: () -> Value) {
        value = value + nextValue()
    }
}

I didn't really change anything fundamental to what you did. Mostly just got rid of the outside GeometryReader and made the frame dependent only on the height being passed in from the PreferenceKey

jnpdx
  • 45,847
  • 6
  • 64
  • 94
  • Hi! Any insight onto why this stops working when I change the font size? I change it for both the TextEditor and the text and I've tried changing padding and multiplying/adding to the textEditorHeight – Erin Donahue Mar 16 '21 at 17:33
  • I can't replicate that on my end (at least on iOS 14.4). Just updated my answer with code that changes the font size and works fine – jnpdx Mar 16 '21 at 18:49
  • hm. It works... unless I use Times font. I can obviously use something else but it is bizarre – Erin Donahue Mar 17 '21 at 17:31
  • update: you have to specify line spacing for Times – Erin Donahue Mar 17 '21 at 18:34
  • Yes I forgot! I will note for future readers that deleting .frame(height: textEditorHeight) from the TextEditor and adding a max/min padding to Text will allow you to set parameters on the size – Erin Donahue Mar 18 '21 at 19:53