Injecting custom behavior during editmode on a TextField in SwiftUI
Last Run on XCODE 11.6 / Swift 5.2
Definitions
‘TextField’ is a View provided in SwiftUI for handling user entered input into an app. As per the documentaion, Apple defines it as
“TextField - A control that displays an editable text interface.”
struct TextFieldEditMode: View {
@State private var someData = ""
var body: some View {
TextField("Type something", text: $someData)
.font(.largeTitle)
}
}
Initializers
The ‘TextField’ has four initializers, and the one we will be using in this post is the one listed below, that provides us with two additional parameters “onEditingChanged” and “onCommit”.
init<S>(S, text: Binding<String>, onEditingChanged: (Bool) -> Void,
onCommit: () -> Void)
Implementation - Basic
The parameter onEditingChanged() takes a closure of the type ‘(Bool) -> Void’ that we as developers need to provide to inject additional functionality. The closure recives a bool value signifying if the TextField is in editMode. Interestingly, this closure also gets triggered on entering the return key.
Lets get started. In the code below, I will update a Text View with the bool value recived by the onEditingChanged() method once we start entering into the field.
struct TextFieldEditMode: View {
@State private var someData = ""
@State private var editFlag = false
var body: some View {
VStack {
Text("Editting Status: \(editFlag.description)")
TextField("Type something", text: $someData,
onEditingChanged: { isBeingEditted in
self.editFlag = isBeingEditted
})
.font(.largeTitle)
}
}
}
TextField not being editted. | TextField being editted. |
---|---|
Implementation - Color Menu
Let’s make something more practical with our learnings. In the code below, we add a ColorMenu() View above the TextField to allow the user to change the foreground color of the input text.
@State private var someData = ""
@State private var editFlag = false
@State private var foregroundColor = Color.primary
var body: some View {
VStack {
if editFlag {
ColorMenu(foregroundColor: $foregroundColor)
}
TextField("Type something", text: $someData,
onEditingChanged: { isBeingEditted in
self.editFlag = isBeingEditted
})
.font(.largeTitle)
.foregroundColor(foregroundColor)
}
}
This is the basic implementation of the ColorMenu() View that we conditionally make visible in our app based on the edit status of the TextField.
struct ColorMenu: View {
@Binding var foregroundColor: Color
var body: some View {
HStack {
Button(action: {self.foregroundColor = .red}) {
Image(systemName: "circle.fill").foregroundColor(.red)
}
Spacer()
Button(action: {self.foregroundColor = .yellow}) {
Image(systemName: "circle.fill").foregroundColor(.yellow)
}
Spacer()
Button(action: {self.foregroundColor = .blue}) {
Image(systemName: "circle.fill").foregroundColor(.blue)
}
Spacer()
Button(action: {self.foregroundColor = .green}) {
Image(systemName: "circle.fill").foregroundColor(.green)
}
Spacer()
Button(action: {self.foregroundColor = .orange}) {
Image(systemName: "circle.fill").foregroundColor(.orange)
}
}
}
}