15

I'm making a sign-in interface for iOS in SwiftUI. The user should be able to easily switch from the username text field to the password text field by tapping the "next" button on the software keyboard. It's working well but the keyboard always bounces a little when switching between the two text fields for some reason. Edit: As suggested in this answer I've added a Spacer into the VStack to make it fill the available space. The text fields aren't bouncing anymore but the keyboard unfortunately still is. I've updated the code and the GIF to reflect my changes.

recording of the issue

After googling a little it seemed like this wasn't a very common issue. This question seemed to be similar to what happens to me but following the answer and wrapping the text fields in a ScrollView or a GeometryReader did not change anything at all. This is my code:

struct AuthenticationView: View {
  @State var userName: String = ""
  @State var userAuth: String = ""
  
  @FocusState var currentFocus: FocusObject?
  enum FocusObject: Hashable { case name, auth }
  
  var body: some View {
    VStack(spacing: 8) {
      TextField("Username", text: $userName)
        .focused($currentFocus, equals: .name)
        .padding(8).background(Color.lightGray)
        .cornerRadius(8).padding(.bottom, 8)
        .textInputAutocapitalization(.never)
        .onSubmit { currentFocus = .auth }
        .autocorrectionDisabled(true)
        .keyboardType(.asciiCapable)
        .textContentType(.username)
        .submitLabel(.next)
      
      SecureField("Password", text: $userAuth)
        .focused($currentFocus, equals: .auth)
        .padding(8).background(Color.lightGray)
        .cornerRadius(8).padding(.bottom, 16)
        .textInputAutocapitalization(.never)
        .onSubmit { currentFocus = nil }
        .autocorrectionDisabled(true)
        .keyboardType(.asciiCapable)
        .textContentType(.password)
        .submitLabel(.done)
      
      Spacer() // This fixes the text fields
      // But it does not fix the keyboard
    }.padding(32)
  }
}
Gadget
  • 183
  • 1
  • 7
  • 1
    Did you find a different fix for this? – Eric Jubber Nov 16 '22 at 05:01
  • This is iOS 16 bug. You can fix this by using UITextField and UITextView. Using becomeFirstResponder would not occur this behavior. art-technologies/swift-focuser is a good choice to fix it but as this repository isn't maintained anymore so maybe you have to fix some problems by yourself. – ST K Apr 17 '23 at 14:13
  • Also see this problem – Nick McConnell Aug 02 '23 at 06:04

1 Answers1

0

Your current layout says:

Put the edit fields into a VStack. Layout the VStack in the parent view by centering it in the available space. Note, that the VStack only uses a minimum size.

Now, when the keyboard appears, the available space of the parent view, i.e. its height, will be reduced accordingly.

Because the VStack is layout in the center, the text fields bounce up and down.

There are a couple of options:

Ensure the VStack extends its height and the text fields are aligned at the top. For example using a Spacer:

    VStack(spacing: 8) {
      TextField("Username", text: $userName)
        ...   
    
      SecureField("Password", text: $userAuth)
        ...
    
      Spacer()
    }.padding(32)

Using a ScrollView:

    ScrollView {

        Spacer(minLength: 80) // give some space at the top

        VStack(spacing: 8) {
          TextField("Username", text: $userName)
          ...   
    
         SecureField("Password", text: $userAuth)
         ...
    
        }.padding(32)
    }

It may not look pretty, but it should give you an idea, where to work on this issue (you may want to use a GeometryReader and a possibly a ScrollView to perfect your layout).

Another option is to use a Form. Put your fields into there, and with a Form you get also a head start which looks pretty nice. The reason why a Form works is because the same reasons why it works with a Spacer (aligns fields on top) and because of a ScrollView.

The fact that the keyboard disappears temporarily when you tap "Next" is unfortunate. I have no solution for this, so far.

CouchDeveloper
  • 18,174
  • 3
  • 45
  • 67