How to Create Floating Textfield in SwiftUI?

Floating text field in SwiftUI

SwiftUI has brought about a paradigm shift in UI development, allowing developers to create declarative and user-friendly interfaces effortlessly. When it comes to crafting forms or login screens, a floating text field can significantly improve the user experience by offering a clear and interactive input method. In this article, we will delve into a Swift implementation of a floating text field using SwiftUI.

Understanding the Code

Let's dissect the essential components of the provided Swift code.

enum TextFieldType {
    case secureField
    case textField
}

This enum defines two cases, secureField and textField, representing the types of text fields that can be created using this implementation.

struct SkyFloatingTextField: View {
    // Properties
    var placeholder: String
    @Binding var text: String
    var textFieldType: TextFieldType
    @State private var isEditing = false
    @State var isSecured: Bool = true
    @FocusState var isSecureFieldFocused: Bool
    @FocusState var isTextFieldFocused: Bool
    @Environment(\.sizeCategory) var sizeCategory

    // Computed Property
    var shouldPlaceHolderMove: Bool {
        isEditing || (text.count != 0)
    }

    // Body
    var body: some View {
        // Main VStack
        VStack {
            // Inner VStack for text field
            VStack(alignment: .leading, spacing: 4) {
                // HStack for text field and toggle button
                HStack(spacing: 15) {
                    // Depending on the field type, render either SecureField or TextField
                    Group {
                        if isSecured {
                            // SecureField
                            SecureField("", text: $text, onCommit: {
                                withAnimation(.easeIn) {
                                    isEditing = false
                                }
                            })
                            .focused($isSecureFieldFocused)
                            // Additional styling for SecureField
                        } else {
                            // TextField
                            TextField("", text: $text, onEditingChanged: { isEdit in
                                withAnimation(.easeIn) {
                                    isEditing = isEdit
                                }
                            })
                            .accentColor(AppColors.textColor)
                            .font(.poppinsRegular(size: 16, category: sizeCategory))
                            .focused($isTextFieldFocused)
                            // Additional styling for TextField
                        }
                    }
                    .padding(.top, 12)

                    // Toggle button for secure field visibility
                    .overlay(alignment: .trailing) {
                        if textFieldType == .secureField {
                            Button {
                                isSecured.toggle()
                            } label: {
                                Image(systemName: isSecured ? "eye.slash" : "eye")
                                    .foregroundColor(AppColors.textColor)
                                    .frame(width: 15, height: 15)
                                    .padding(13)
                            }
                        }
                    }
                }
                // Placeholder text animation
                .background(
                    Text(placeholder)
                        .offset(y: shouldPlaceHolderMove ? -12 : 0)
                        .foregroundStyle(AppColors.textColor)
                        .font(.poppinsRegular(size: shouldPlaceHolderMove ? 11 : 15, category: sizeCategory))
                    , alignment: .leading
                )
            }
            // Styling for the text field container
            .frame(height: 50)
            .padding(.horizontal, 8)
            .background(
                RoundedRectangle(cornerRadius: 8)
                    .stroke(AppColors.textColor, style: StrokeStyle(lineWidth: 0.5))
            )
            // Tap gesture to toggle focus on appearance
            .onTapGesture {
                withAnimation(.linear(duration: 8.0)) {
                    isSecureFieldFocused.toggle()
                    isTextFieldFocused.toggle()
                }
            }
            // Set initial state for SecureField
            .onAppear(perform: {
                isSecured = textFieldType == .secureField
            })
        }
    }
}

Deeper Dive into Key Features


Focus State and Dynamic Interaction

The use of @FocusState allows for dynamic management of focus states, ensuring a seamless transition between text fields and a responsive user interface. Tapping the text field triggers a focus state toggle, accompanied by a smooth animation.

Adaptive Font Sizing with SizeCategory

The @Enviroment(\.SizeCategory) property facilitates dynamic font sizing based on the user's preferred content size. This adaptability ensures optimal readability and accessibility across different device configurations.

SecureField and Eye Icon Toggle

The implementation incorporates a secure text field (SecureField) for password input, complete with an eye icon toggle button. This button dynamically switches between obscured and readable text, offering users control over password visibility.

Placeholder Animation

The shouldPlaceHolderMove computed property orchestrates an elegant animation that adjusts the position and size of the placeholder text. This subtle touch enhances the user experience by providing visual cues about the active state of the text field.

Rounded Aesthetics with RoundedRectangle

The use of RoundedRectangle provides a visually appealing border around the text field, contributing to a polished and modern design. The stroke style further refines the appearance, adding a delicate outline to the text input area.

Tap Gesture Interaction

A tap gesture is employed to toggle focus states on appearance, creating a user-friendly interaction that seamlessly integrates with the overall design. The duration of the animation is carefully calibrated to ensure a delightful and engaging experience.

Implementing the Floating TextField

To integrate this floating text field into your SwiftUI project, follow these steps.

  1. Copy the SkyFloatingTextField struct and the TextFieldType enum into your SwiftUI project.
  2. Create an instance of SkyFloatingTextField within your view, providing the necessary parameters like placeholder, text, and textFieldType.
  3. Customize the appearance and behavior by adjusting the styling and animations within the SkyFloatingTextField struct.
  4. Utilize the preview code as a visual reference to tailor the floating text field to your application's aesthetics.

By incorporating this Swift implementation of a floating text field, you can elevate the overall look and feel of your SwiftUI app. Tailor the design and behavior to align with your specific requirements, delivering a seamless and visually pleasing user experience.

Conclusion

This comprehensive guide provides a thorough exploration of the Swift implementation for a floating text field in SwiftUI. Embrace the provided code, experiment with customization options, and empower your users with an enhanced and interactive text input experience.


Similar Articles