Dynamic TextEditor overlapping with other views
Asked Answered
D

1

1

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()
        }
    }
Domingodominguez answered 5/3, 2021 at 1:24 Comment(0)
P
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

Pinch answered 5/3, 2021 at 5:33 Comment(5)
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 textEditorHeightDomingodominguez
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 finePinch
hm. It works... unless I use Times font. I can obviously use something else but it is bizarreDomingodominguez
update: you have to specify line spacing for TimesDomingodominguez
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 sizeDomingodominguez

© 2022 - 2024 — McMap. All rights reserved.