Environment value isFocused doesn't seem to work when we want to observe focus state of SwiftUI textfield. Is there any other way to do this, besides passing the value to TextFieldStyle's init (which we would have to do for every Textfield)? Doesn't work on device either.
What is the preferred way of changing Textfield's appearance when its focus state changes?
Example:
SwiftUI TextFieldStyle defined as follows:
struct MyTextFieldStyle: TextFieldStyle {
@Environment(\.isFocused) var isFocused: Bool
func _body(configuration: TextField<_Label>) -> some View {
configuration
.padding()
.overlay(
RoundedRectangle(
cornerRadius: 10.0, style: .continuous
)
.stroke(isFocused ? .green : .gray, lineWidth: 3)
)
.accentColor(Color(uiColor: .white))
}
}
#if DEBUG
private struct TestView: View {
@FocusState private var focusedTextfield: FocusField?
enum FocusField: Hashable {
case textfield1, textfield2
}
var body: some View {
VStack(spacing: 16) {
TextField("hello", text: .constant("Hi"))
.textFieldStyle(MyTextFieldStyle())
.focused($focusedTextfield, equals: .textfield1)
TextField("hello", text: .constant("Hi"))
.textFieldStyle(MyTextFieldStyle())
.focused($focusedTextfield, equals: .textfield2)
}.onAppear {
focusedTextfield = .textfield1
}
}
}
struct MyTextfieldStyle_Previews: PreviewProvider {
static var previews: some View {
ZStack {
TestView()
}
}
}
#endif
// EDIT: Working solution based on https://mcmap.net/q/1957351/-swiftui-focus-state-api-environment-variable-not-working
struct MyTextFieldStyle: TextFieldStyle {
@FocusState var isFocused: Bool
func _body(configuration: TextField<_Label>) -> some View {
configuration
.padding()
.focused($isFocused)
.overlay(
RoundedRectangle(
cornerRadius: 10.0, style: .continuous
)
.stroke(isFocused ? .green : .gray, lineWidth: 3)
)
.accentColor(Color(uiColor: .white))
}
}
#if DEBUG
private struct TestView: View {
@FocusState private var focusedTextfield: FocusField?
enum FocusField: Hashable {
case textfield1, textfield2
}
var body: some View {
VStack(spacing: 16) {
TextField("hello", text: .constant("Hi"))
.textFieldStyle(MyTextFieldStyle())
.focused($focusedTextfield, equals: .textfield1)
TextField("hello", text: .constant("Hi"))
.textFieldStyle(MyTextFieldStyle())
.focused($focusedTextfield, equals: .textfield2)
}.onAppear {
DispatchQueue.main.async {
focusedTextfield = .textfield1
}
}
}
}
struct MyTextFieldStyle_Previews: PreviewProvider {
static var previews: some View {
ZStack {
TestView()
}
}
}
#endif