Issue #776
We need to use a custom Binding to trigger onChange as onEditingChanged is only called when the user selects the textField, and onCommit is only called when return or done button on keyboard is tapped.
import UIKit
import SwiftUI
import EasySwiftUI
struct SearchBar: View {
@Binding
var searchText: String
let onChange: () -> Void
@State
private var showsCancelButton: Bool = false
var body: some View {
return HStack {
textField
cancelButton
}
}
private var searchTextBinding: Binding<String> {
Binding<String>(get: {
searchText
}, set: { newValue in
DispatchQueue.main.async {
searchText = newValue
onChange()
}
})
}
private var textField: some View {
HStack {
Image(systemName: SFSymbol.magnifyingglass.rawValue)
TextField("Search", text: searchTextBinding, onEditingChanged: { isEditing in
withAnimation {
self.showsCancelButton = true
}
onChange()
}, onCommit: {
// No op
})
.foregroundColor(.primary)
Button(action: {
self.searchText = ""
}) {
Image(systemName: SFSymbol.xmarkCircleFill.rawValue)
.opacity(searchText == "" ? 0 : 1)
}
}
.padding(EdgeInsets(top: 8, leading: 6, bottom: 8, trailing: 6))
.foregroundColor(.secondary)
.background(Color(.systemBackground))
.cornerRadius(10.0)
}
@ViewBuilder
private var cancelButton: some View {
if showsCancelButton {
Button("Cancel") {
UIApplication.shared.endEditing(true)
withAnimation {
self.searchText = ""
self.showsCancelButton = false
}
onChange()
}
.foregroundColor(Color(.systemBlue))
}
}
}
extension UIApplication {
func endEditing(_ force: Bool) {
self.windows
.filter{$0.isKeyWindow}
.first?
.endEditing(force)
}
}
Start the conversation