Rafa Log
Rafa Log

Reputation: 1

Keyboard in swiftui is overlapping UI elements

Whenever i click in my textfield, the keyboard is overlapping my button, and i would like that the view would go up to have space between the button and keyboard

Simulator image

this is my code

import SwiftUI

@MainActor
struct SignUpView: View {
    
    @State private var loginVM = LoginViewModel()
    @State private var isPasswordVisible: Bool = false
    @FocusState private var focusField: Field?
    
    var body: some View {
        ScrollViewReader { scrollView in
            ScrollView {
                VStack {
                    header
                    signUpText
                    signUpFields
                    button
                }
                .padding(.horizontal, 30)
                .onAppear {
                    focusField = .fullName
                }
                .background(Color.background.onTapGesture {
                    focusField = nil
                })
            }
            .clipped() //Clips the view within the scrollView
            .background(Color.background.ignoresSafeArea())
        }
    }
}

extension SignUpView {
    var header: some View {
        Image(.signUp)
            .resizable()
            .scaledToFill()
            .frame(width: 250, height: 210)
    }
    
    var signUpText: some View {
        VStack(alignment: .leading, spacing: 30) {
            Text("Welcome to Calmify")
                .font(.title)
                .fontWeight(.semibold)
                .foregroundStyle(Constants.backgroundInvert)
                .frame(maxWidth: .infinity, alignment: .leading)
        }
    }
    
    var signUpFields: some View {
        VStack(spacing: 30) {
            
            CustomTextfield(iconPrefix: Image(systemName: "person.fill"), text: $loginVM.name, placeHolder: "Full name", textContentType: .name)
                .focused($focusField, equals: .fullName)
                .submitLabel(.next)
                .onSubmit {
                    focusField = .email
                }
                .onChange(of: loginVM.name) {
                    loginVM.buttonEnableForSignUp()
                }
            
            CustomTextfield(iconPrefix: Text("@"), text: $loginVM.email, placeHolder: "Email", textContentType: .emailAddress)
                .focused($focusField, equals: .email)
                .keyboardType(.emailAddress)
                .accessibilityLabel("Registration")
                .textInputAutocapitalization(.never)
                .submitLabel(.next)
                .onSubmit {
                    focusField = .password
                }
                .onChange(of: loginVM.email) {
                    loginVM.buttonEnableForSignUp()
                }
            
            CustomSecureTexfield(text: $loginVM.password, showPassword: $isPasswordVisible, showForgetPassword: false, forgetPasswordAction: nil)
                .focused($focusField, equals: .password)
                .submitLabel(.done)
                .onSubmit {
                    focusField = nil
                }
                .onChange(of: loginVM.password) {
                    loginVM.buttonEnableForSignUp()
                }
        }
        .padding(.top, 10)
    }
    
    var button: some View {
        VStack {
            Button {
                Task {
                    do {
                        try await loginVM.signUp()
                        print("cuenta creada")
                        loginVM.goToHomeView.toggle()
                    } catch {
                        print(error.localizedDescription)
                    }
                }
            } label: {
                Text("Enter")
                    .foregroundStyle(.white)
                    .fontWeight(.semibold)
                    .frame(width: 200 ,height: 50)
                    .background(loginVM.buttonIsEnable ? .blue : .gray)
                    .clipShape(.rect(cornerRadius: 25))
                
            }
            .disabled(!loginVM.buttonIsEnable)
        }
        .fullScreenCover(isPresented: $loginVM.goToHomeView){
            Home()
        }
        .padding(.top, 30)
        .padding(.bottom, 30)
    }
}


struct CustomTextfield<Icon: View>: View {
    
    let iconPrefix: Icon
    @Binding var text: String
    let placeHolder: String
    let textContentType: UITextContentType

    var body: some View {
        HStack {
            iconPrefix
                .foregroundStyle(Color(.systemGray))
                .padding(.trailing, 20)
            
            VStack {
                TextField(placeHolder, text: $text)
                    .textContentType(textContentType)
                Divider()
                    .background(Constants.backgroundInvert)
            }
        }
    }
}


struct CustomSecureTexfield: View {
    @Binding var text: String
    @Binding var showPassword: Bool
    let showForgetPassword: Bool
    let forgetPasswordAction: (() -> Void)?

    var body: some View {
        HStack {
            Image(systemName: "lock.fill")
                .foregroundStyle(Color(.systemGray))
                .padding(.trailing, 20)
            VStack {
                HStack {
                    if showPassword {
                        TextField("Password", text: $text)
                    } else {
                        SecureField("Password", text: $text)
                            .textContentType(.password)
                    }
                    Spacer()
                    Button {
                        showPassword.toggle()
                    } label: {
                        Image(systemName: showPassword ? "eye.slash.fill" : "eye.fill")
                            .imageScale(.small)
                            .foregroundStyle(.backgroundInvert.opacity(0.5))
                            .frame(height: 25)
                    }
                    
                    if showForgetPassword, let forgetPasswordAction = forgetPasswordAction {
                        Button {
                                 forgetPasswordAction()
                            
                        } label: {
                            Text("Forgot?")
                                .font(.subheadline)
                                .fontWeight(.semibold)
                        }
                        .padding(.leading, 10)
                    }
                    
                    Spacer()
                }
                Divider()
                    .background(Constants.backgroundInvert)
            }
        }
    }
}

I was using scrollReaderView but without success.

im using custom textfifields that i put it in the code, also i notice that if im not using scrollview, the screen automatically goes up when the keyboards appears, but when using scrollview kind of loose that effects.

there is something that im missing?

anyone had the same issue? please some asnwer. thank you

Upvotes: -1

Views: 86

Answers (0)

Related Questions