SwiftUI - Keyboard avoidance pushes content into navigation bar

Viewed 508

I have a view with some text fields. Selecting the top text field causes keyboard avoidance to push everything up to keep the bottom text field visible. In this case, it pushes the "Input 1" text above the top text field into the navigation bar, hiding it.

struct Settings: View {
    @State private var input1: String = ""
    @State private var input2: String = ""
    @State private var input3: String = ""
    @State private var input4: String = ""
    @State private var input5: String = ""
    
    init() {
        let coloredAppearance = UINavigationBarAppearance()
        coloredAppearance.configureWithTransparentBackground()
        coloredAppearance.backgroundColor = .gray

        UINavigationBar.appearance().standardAppearance = coloredAppearance
        UINavigationBar.appearance().compactAppearance = coloredAppearance
        UINavigationBar.appearance().scrollEdgeAppearance = coloredAppearance
    }
    
    var body: some View {
        NavigationView {
            VStack(spacing: 16) {
                Group {
                    VStack {
                        Text("Input 1")
                            .frame(maxWidth: .infinity, alignment: .leading)
                        TextField("", text: $input1)
                            .disableAutocorrection(true)
                            .padding()
                            .overlay(RoundedRectangle(cornerRadius: 5).stroke(.gray))
                    }
                }
                Group {
                    VStack {
                        Text("Input 2")
                            .frame(maxWidth: .infinity, alignment: .leading)
                        TextField("", text: $input2)
                            .disableAutocorrection(true)
                            .padding()
                            .overlay(RoundedRectangle(cornerRadius: 5).stroke(.gray))
                    }
                }
                Group {
                    VStack {
                        Text("Input 3")
                            .frame(maxWidth: .infinity, alignment: .leading)
                        TextField("", text: $input3)
                            .disableAutocorrection(true)
                            .padding()
                            .overlay(RoundedRectangle(cornerRadius: 5).stroke(.gray))
                    }
                }
                Group {
                    VStack {
                        Text("Input 4")
                            .frame(maxWidth: .infinity, alignment: .leading)
                        TextField("", text: $input4)
                            .disableAutocorrection(true)
                            .padding()
                            .overlay(RoundedRectangle(cornerRadius: 5).stroke(.gray))
                    }
                }
                Spacer()
            }
            .navigationBarTitle("Header", displayMode: .inline)
        }
        .ignoresSafeArea()
    }
}

Without keyboard

With keyboard

Does anyone have a way to prevent this? I've tried spacers without success. While this might keep the text visible, it creates a space between the navigation bar and the text when the keyboard isn't open. I've also tried messing with ignoresSafeArea(.keyboard).

Ideally, if the top text field is selected, the keyboard should cover the bottom text fields without pushing anything up. I'd like to only push content up if necessary to keep the currently selected text field visible. Anyone have a way to do this? Thanks in advance.

0 Answers
Related