Reputation: 415
In this SwiftUI code, I have a view that contains a search bar and underneath the search bar are some filter tags that are in a capsule shape & an image.
When the search bar is tapped, the keyboard shifts up the view and the filter tags cover the search bar.
I want to alter the code so that showingTags is set to false when the search bar has been tapped in order to avoid this UI error
I tried using .onTapGesture{} on the .searchable modifier but this didn't seem to work. How can I make sure the tags are not shown when the search bar has been tapped?
Here is my code:
struct ProductSearchView: View {
@StateObject var marketplaceModel = MarketplaceViewModel()
@State var searchText = ""
@State var product_array_status = true
@State var product_array_status_search = false
@State var product_array_status_tags = false
@State var showingTags: Bool = true
var body: some View {
ZStack {
Color("BG")
.ignoresSafeArea()
VStack {
if showingTags {
TagView()
}
if product_array_status_search {
VStack(spacing: 15) {
ScrollView(.vertical, showsIndicators: false) {
ForEach(marketplaceModel.filteredProduct.filter { ($0.product_name ?? "").contains(searchText)}, id: \.self) { product in
ProductSearchRow(productData: product)
}
}
}
.onAppear {
showingTags.toggle()
}
} else if product_array_status_tags {
VStack(spacing: 15) {
ScrollView(.vertical, showsIndicators: false) {
ForEach(marketplaceModel.product_tag_array, id: \.self) { product in
ProductSearchRow(productData: product)
}
}
}
} else {
Image("PlaceholderImage")
.resizable()
}
Spacer()
}
}
.searchable(text: $searchText, placement: .navigationBarDrawer(displayMode: .always))
.onAppear {
let defaults = UserDefaults.standard
let keyString = defaults.string(forKey: "key") ?? ""
self.marketplaceModel.fetchProductData(key: keyString)
}
.onChange(of: marketplaceModel.search, perform: { value in
// to avoid Continues Search requests....
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
if value == marketplaceModel.search && marketplaceModel.search != ""{
// Search Data....
marketplaceModel.filterData()
}
}
if marketplaceModel.search == ""{
// reset all data....
withAnimation(.linear) {
product_array_status = true
product_array_status_search = false
}
}
})
}
}
How do I ensure TagView() is not displayed when the search bar provided by .searchable has been tapped?
Upvotes: 0
Views: 480
Reputation: 273540
You can use the environment value isSearching
to detect if the search text field is focused.
You should declare an Environment
, not in ProductSearchView
, but in one of the subviews of the searchable
view. Since this determines the visibility of the TagView
, it's probably the easiest if you put it in TagView
:
struct TagView: View {
@Environment(\.isSearching) var isSearching: Bool
var body: some View {
if !isSearching {
// put the original contents of "body" here...
}
// if isSearching is true, then the body is empty. The view is basically "hidden".
}
}
Now you don't even need showingTags
!
Upvotes: 2