Still a beginner in SwiftUI animations and struggling with this issue.
I have a custom search bar that resembles its native counterpart. Everything's working fine except for the inserting/removing views animations. Here's what's happening:
Only step 1 is animating correctly, steps 2 and 3 are not.
Here's the code for the search bar component:
struct CustomSearchBar: View {
var prompt: String
@Binding var query: String
@FocusState private var isEditing: Bool
@State var onSubmit: () -> Void
var body: some View {
HStack(alignment: .center) {
TextField(prompt, text: $query)
.onSubmit(onSubmit)
.focused($isEditing)
.padding(8)
.padding(.horizontal, 25)
.background(Color(.systemGray6))
.overlay(
HStack {
Image(systemName: "magnifyingglass")
.foregroundColor(.gray)
.frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
.padding(.leading, 8)
if isEditing {
Button {
self.query = ""
} label: {
Image(systemName: "multiply.circle.fill")
.foregroundColor(.gray)
.padding([.leading, .trailing], 8)
}
.transition(.opacity)
}
}
)
.onTapGesture {
self.isEditing = true
}
.submitLabel(.search)
.transition(.slide)
if isEditing {
Button {
self.isEditing = false
self.query = ""
} label: {
Text("Cancel")
.foregroundColor(.red)
}
.padding(.trailing, 10)
.transition(.opacity)
}
}
.animation(.linear(duration: 0.3), value: isEditing)
}
}
And how to use it:
struct Search: View {
@State var query: String = ""
@FocusState private var searchIsFocused: Bool
var body: some View {
CustomSearchBar(prompt: "Search", query: $query, onSubmit: { submittedSearch() })
.focused($searchIsFocused)
}
func submittedSearch() {
// do something with search
}
}
I tried wrapping self.isEditing = false
in withAnimation
blocks but it results in no animation at all. I find it using the animation
modifier makes more sense, but it's not detecting subview insertion/removal.
I came across several examples and they all work out like what I posted but, unfortunately, I can't spot the error in my case...
Workaround, use @FocusState
only for the focused
modifier, and create a @State
variable to control the animations.
@FocusState private var focused: Bool {
didSet {
self.editing = self.focused
}
}
@State private var editing = false