Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a height difference between a TextField and SecureField in SwiftUI?

Tags:

ios

swiftui

enter image description here

I'm building a simple login screen and I noticed that when I change between a TextField and a SecureField my screen moves a little and I think it's because their heights are changing? Or maybe I'm doing something wrong?

Here's the code:

struct LoginView: View {
    @State var username: String
    @State var password: String
    @State var showingPassword: Bool = false
    
    var body: some View {
            VStack(spacing: 15) {
                Text("Welcome")
                    .font(.largeTitle)
                    .bold()
                    .padding(.bottom)
                TextField("Username", text: $username)
                    .customTextField()
                    .overlay(RoundedRectangle(cornerRadius: 10).stroke(Color("charcoal"), lineWidth: 0.6))
                HStack {
                    if showingPassword {
                        TextField("Password", text: $password)
                            .customTextField()
                            .overlay(RoundedRectangle(cornerRadius: 10).stroke(Color("charcoal"), lineWidth: 0.6))
                            .border(.pink)
                        Image(systemName: "eye.slash")
                            .onTapGesture {
                                showingPassword.toggle()
                            }
                            .border(.pink)
                    } else {
                        SecureField("Password", text: $password)
                            .customTextField()
                            .overlay(RoundedRectangle(cornerRadius: 10).stroke(Color("charcoal"), lineWidth: 0.6))
                            .border(.green)
                        Image(systemName: "eye")
                            .onTapGesture {
                                showingPassword.toggle()
                            }
                            .foregroundColor(Color("charcoal"))
                            .border(.green)
                    }
                }
            }
            .padding(.horizontal)
    }
}

and the modifier:

struct TextFieldModifier: ViewModifier {
    func body(content: Content) -> some View {
        content
            .padding(.horizontal)
            .padding(.vertical, 12)
            .overlay(RoundedRectangle(cornerRadius: 10).stroke(Color.gray, lineWidth: 0.6))
            .lineLimit(5)
    }
}

extension View {
    func customTextField() -> some View {
        modifier(TextFieldModifier())
    }
}
like image 599
Sara Avatar asked Feb 03 '26 09:02

Sara


2 Answers

Yes, there is indeed a height difference. You can inspect it by using Xcode's UI inspector on a view as simple as:

var body: some View {
    VStack {
        TextField("Username", text: $username)
        SecureField("Password", text: $password)
    }
}

On my simulator, the text field has height 22, and the secure field has height 21.

enter image description here

enter image description here

This difference in height is also visible in the picture in Apple's documentation page for SecureField. The picture is:

enter image description here

You can try opening the image up in Preview.app or similar and count the pixels (I did that!).

I'm not sure if this difference is intended or not.

like image 118
Sweeper Avatar answered Feb 05 '26 23:02

Sweeper


This is indeed janky! I had the same problem and solved it by adding .frame(height: 22) to both fields, It's probably not needed on the TextField, but I decided to add it there, in the event that it get's rendered differently in some case.

Here's my full code snippet:

HStack {
    Group {
        if showPassword {
            TextField("Password",
                        text: $password,
                        prompt: Text("Password"))
            .frame(height: 22)
        } else {
            SecureField("Password",
                        text: $password,
                        prompt: Text("Password"))
            .frame(height: 22)
        }
    }
    .padding(10)

    Button {
        showPassword.toggle()
    } label: {
        Image(systemName: showPassword ? "eye.slash" : "eye")
            .padding(.horizontal)
    }
}
like image 25
Circle B Avatar answered Feb 05 '26 23:02

Circle B



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!