skip to Main Content

If after activating TextField I press Open link button, NavigationLink will be opened. After that if I return back to previous screen, VStack with TextField will stay in the middle of the screen, because bottom SafeArea will be expanded by keyboard. This happening if first view in ZStack is ScrollView. It should go back to bottom after keyboard is disabled. How can I fix that?

struct ContentView: View {
  @State private var text = ""
  
  var body: some View {
    NavigationStack {
      ZStack(alignment: .bottom) {
        ScrollView {
          Color.green.opacity(0.2)
            .frame(height: 1000)
        }
        .ignoresSafeArea(.keyboard)
        
        VStack {
          TextField("", text: $text, prompt: Text("Input"))
            .textFieldStyle(.roundedBorder)
            .padding()
          NavigationLink("Open link") {
            Text("Details view")
          }
        }
        .background { Color.red }
        .background(ignoresSafeAreaEdges: .bottom)
      }
    }
  }
}

enter image description here

2

Answers


  1. You can try using the @FocusState property wrapper. Add 3 following command lines:

    //1 
    @FocusState private var nameIsFocused: Bool
    
    //2
    .focused($nameIsFocused)
    
    //3
    .simultaneousGesture(TapGesture().onEnded({ _ in
       nameIsFocused = false
    }))
    

    The code you wrote looks like this:

    struct ContentView: View {
      @State private var text = ""
      //1
      @FocusState private var nameIsFocused: Bool
    
      var body: some View {
        NavigationStack {
          ZStack(alignment: .bottom) {
            ScrollView {
              Color.green.opacity(0.2)
                .frame(height: 1000)
            }
            .ignoresSafeArea(.keyboard)
            
            VStack {
              TextField("", text: $text, prompt: Text("Input"))
                //2
                .focused($nameIsFocused)
                .textFieldStyle(.roundedBorder)
                .padding()
                
              NavigationLink("Open link") {
                Text("Details view")
              }
              //3
              .simultaneousGesture(TapGesture().onEnded({ _ in
                  nameIsFocused = false
              }))
            }
            .background { Color.red }
            .background(ignoresSafeAreaEdges: .bottom)
          }
        }
      }
    }
    

    Result:

    Result

    Hope it is useful for you!

    Login or Signup to reply.
  2. This bug is only on iOS 16.2 and 16.3 (and maybe 16.1, couldn’t test it). On 16.0 and 16.4 it doesn’t appear anymore.

    So for now we closed the keyboard before pushing a new UIViewController. We’re still using SwiftUI inside a normal UIViewController so we did it like this:

            // Need to clear search field focus, otherwise on iOS 16.2 and 16.3 keyboard insets will stay
            self.view.endEditing(true)
            // Need to push after delay, otherwise on iOS 16.2 and 16.3 keyboard insets will stay
            DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.01) {
                self.navigationController?.pushViewController(DetailViewController(item: item), animated: true)
            }
    

    As you can see I also needed to introduce a small delay, otherwise it still wasn’t working (would work on simulator with iOS 16.2, but not on device with iOS 16.3.1).

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search