Learn how to work with Xcode Previews in SwiftData App. SwiftData in combination with SwiftUI…
Mastering Focus in SwiftUI: Using .focused Modifier
SwiftUI’s .focused
modifier allows you to control and observe the focus state of your views. This is particularly useful for managing user input fields and ensuring a smooth user experience. In this tutorial, we’ll explore how to use the .focused
modifier with unique and interesting examples that are simple to understand for developers of all levels.
Introduction to .focused
The .focused
modifier binds the focus state of a view to a Boolean state value. When the bound value is true, the view receives focus; when false, it loses focus. This allows you to programmatically manage the focus state of your views.
Basic Example
Let’s start with a basic example where we manage the focus state of a TextField
in a form, including a visual indicator for when the field is focused.
import SwiftUI
struct FocusedExampleView: View {
@State private var username: String = ""
@State private var password: String = ""
@FocusState private var usernameFieldIsFocused: Bool
@FocusState private var passwordFieldIsFocused: Bool
@State private var showPasswordHint = false
var body: some View {
VStack(spacing: 20) {
TextField("Username", text: $username)
.focused($usernameFieldIsFocused)
.padding()
.background(usernameFieldIsFocused ? Color.yellow.opacity(0.3) : Color.clear)
.cornerRadius(10)
.overlay(
RoundedRectangle(cornerRadius: 10)
.stroke(usernameFieldIsFocused ? Color.blue : Color.gray, lineWidth: 2)
)
SecureField("Password", text: $password)
.focused($passwordFieldIsFocused)
.padding()
.background(passwordFieldIsFocused ? Color.yellow.opacity(0.3) : Color.clear)
.cornerRadius(10)
.overlay(
RoundedRectangle(cornerRadius: 10)
.stroke(passwordFieldIsFocused ? Color.blue : Color.gray, lineWidth: 2)
)
if showPasswordHint {
Text("Password must be at least 8 characters long.")
.foregroundColor(.red)
}
Button("Submit") {
validateForm()
}
.padding()
.background(Color.blue)
.foregroundColor(.white)
.cornerRadius(10)
}
.padding()
}
private func validateForm() {
if username.isEmpty {
usernameFieldIsFocused = true
} else if password.count < 8 {
passwordFieldIsFocused = true
showPasswordHint = true
} else {
showPasswordHint = false
print("Form submitted")
}
}
}
Explanation
- State Variables: We use
@State
variables to store the input values for the username and password fields, and to manage the visibility of the password hint. - FocusState: We use
@FocusState
property wrappers to track the focus state of the username and password fields. - TextField and SecureField: The
TextField
for the username and theSecureField
for the password are each bound to their respective focus states using the.focused
modifier. - Visual Indicators: We change the background color and border color of the fields to indicate when they are focused.
- Form Validation: The
validateForm
function checks if the username is empty or if the password is less than 8 characters long. It sets the focus to the appropriate field and displays a hint if necessary. - Submit Button: The “Submit” button triggers the form validation logic.
Advanced Example: Managing Multiple Focused Fields
In a more complex form, you might need to manage multiple fields and their focus states. Let’s extend our example to include an email field and implement a more sophisticated focus management, with visual indicators for each field.
import SwiftUI
struct AdvancedFocusedExampleView: View {
@State private var username: String = ""
@State private var email: String = ""
@State private var password: String = ""
@FocusState private var usernameFieldIsFocused: Bool
@FocusState private var emailFieldIsFocused: Bool
@FocusState private var passwordFieldIsFocused: Bool
@State private var showPasswordHint = false
var body: some View {
VStack(spacing: 20) {
TextField("Username", text: $username)
.focused($usernameFieldIsFocused)
.padding()
.background(usernameFieldIsFocused ? Color.yellow.opacity(0.3) : Color.clear)
.cornerRadius(10)
.overlay(
RoundedRectangle(cornerRadius: 10)
.stroke(usernameFieldIsFocused ? Color.blue : Color.gray, lineWidth: 2)
)
TextField("Email", text: $email)
.focused($emailFieldIsFocused)
.padding()
.background(emailFieldIsFocused ? Color.yellow.opacity(0.3) : Color.clear)
.cornerRadius(10)
.overlay(
RoundedRectangle(cornerRadius: 10)
.stroke(emailFieldIsFocused ? Color.blue : Color.gray, lineWidth: 2)
)
.keyboardType(.emailAddress)
.autocapitalization(.none)
SecureField("Password", text: $password)
.focused($passwordFieldIsFocused)
.padding()
.background(passwordFieldIsFocused ? Color.yellow.opacity(0.3) : Color.clear)
.cornerRadius(10)
.overlay(
RoundedRectangle(cornerRadius: 10)
.stroke(passwordFieldIsFocused ? Color.blue : Color.gray, lineWidth: 2)
)
if showPasswordHint {
Text("Password must be at least 8 characters long.")
.foregroundColor(.red)
}
Button("Submit") {
validateForm()
}
.padding()
.background(Color.blue)
.foregroundColor(.white)
.cornerRadius(10)
}
.padding()
}
private func validateForm() {
if username.isEmpty {
usernameFieldIsFocused = true
} else if !isValidEmail(email) {
emailFieldIsFocused = true
} else if password.count < 8 {
passwordFieldIsFocused = true
showPasswordHint = true
} else {
showPasswordHint = false
print("Form submitted")
}
}
private func isValidEmail(_ email: String) -> Bool {
// Simple email validation
let emailRegEx = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}"
let emailPredicate = NSPredicate(format:"SELF MATCHES %@", emailRegEx)
return emailPredicate.evaluate(with: email)
}
}
Explanation
- Multiple Fields: We apply the same visual indicator logic to the username, email, and password fields.
- Form Validation: The validation logic ensures the correct field is focused based on the validation outcome.
- Email Field: The email field has its own focus state and visual indicators.
By adding these visual cues, users can easily identify which field is currently active, enhancing the user experience.
Conclusion
Using the .focused
modifier in SwiftUI allows you to control and observe the focus state of your views, enhancing the user experience by managing input fields efficiently. By following these examples, you can implement sophisticated focus management in your SwiftUI applications.