I have a view with a filter bar. One says "Shirts" & the other says "Trousers". When "Shirts" is selected, it displays a grid view of shirts. When "Trousers" is selected in the filter bar, it shows a grid view of trousers.
When I tap on an item (a shirt or a pair of trousers) it takes me to a different view (showing the product in more detail). However, the filter bar remains. I need to hide the filter bar when an item is tapped and it takes the user to a detail view.
I need to hide the marketplacefilterbar view when a product is tapped.
My ViewModel for the filter bar is:
enum MarketplaceFilterViewModel: Int, CaseIterable {
case shirts
case trousers
var title: String {
switch self {
case .shirts: return "Shirts"
case .trousers: return "Trousers"
}
}
}
Some code from the MarketplaceViewModel:
class MarketplaceViewModel: NSObject, ObservableObject {
@Published var search = ""
// Shirt Data...
@Published var shirts: [Shirt] = []
@Published var filteredShirt: [Shirt] = []
// Trouser Data...
@Published var trousers: [Trouser] = []
@Published var filteredTrouser: [Trouser] = []
}
Code for the marketplace view is:
ScrollView(.vertical, showsIndicators: false) {
VStack(spacing: 10){
marketplaceFilterBar
if selectedMarketplaceFilter == .raise {
MarketplaceShirtView()
}
if selectedMarketplaceFilter == .save {
MarketplaceTrouserView()
}
}
}
var marketplaceFilterBar: some View {
VStack {
HStack(spacing: 15){
Image("Logo")
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: 60.0, height: 60.0)
.padding(EdgeInsets.init(top: 0, leading: 45, bottom: 0, trailing: 0))
Spacer(minLength: 0)
}
.padding([.horizontal,.top])
HStack {
ForEach(MarketplaceFilterViewModel.allCases, id: \.rawValue) { item in
VStack {
Text(item.title)
.font(.headline)
.fontWeight(selectedMarketplaceFilter == item ? .semibold: .regular)
.foregroundColor(selectedMarketplaceFilter == item ? .black: .gray)
if selectedMarketplaceFilter == item {
Capsule()
.foregroundColor(Color("LightBlue"))
.frame(height: 3)
.matchedGeometryEffect(id: "filter", in: animation)
} else {
Capsule()
.foregroundColor(Color(.clear))
.frame(height: 3)
}
}
.onTapGesture {
withAnimation(.easeInOut) {
self.selectedMarketplaceFilter = item
}
}
}
}
.overlay(Divider().offset(x: 0, y: 16))
}
}
Code for the Shirt Detail View:
struct ShirtDetailView: View {
@Binding var shirtData : Shirt!
@Binding var showDetailShirt: Bool
@Namespace var animation: Namespace.ID
// Shared Data Model...
@EnvironmentObject var sharedData: SharedDataModel
@EnvironmentObject var marketplaceData: MarketplaceViewModel
ScrollView {
VStack{
HStack {
Button(action: {
withAnimation(.easeOut){showDetailShirt.toggle()}
}) {
Image(systemName: "arrow.backward.circle.fill")
.foregroundColor(.gray)
.frame(width: 40, height: 40)
.background(Color.white,in: RoundedRectangle(cornerRadius: 10, style: .continuous))
.shadow(color: .black.opacity(0.1), radius: 5, x: 5, y: 5)
}
Text(shirtData.shirt_name)
.font(.largeTitle)
.fontWeight(.heavy)
.foregroundColor(.black)
}
VStack(spacing: 10){
WebImage(url: URL(string: shirtData.shirt_image))
.resizable()
.aspectRatio(contentMode: .fill)
.edgesIgnoringSafeArea(.all)
.cornerRadius(15)
Text("Details")
.opacity(0.7)
.frame(maxWidth: .infinity,alignment: .leading)
.padding(.bottom)
HStack(spacing: 15) {
Text(shirtData.shirt_details)
.font(.system(size: 18))
.padding()
}
}
}
}
Code for the Trouser Detail View:
struct TrouserDetailView: View {
@Binding var trouserData : Trouser!
@Binding var showDetailTrouser: Bool
@Namespace var animation: Namespace.ID
// Shared Data Model...
@EnvironmentObject var sharedData: SharedDataModel
@EnvironmentObject var marketplaceData: MarketplaceViewModel
ScrollView {
VStack{
HStack {
Button(action: {
withAnimation(.easeOut){showDetailTrouser.toggle()}
}) {
Image(systemName: "arrow.backward.circle.fill")
.foregroundColor(.gray)
.frame(width: 40, height: 40)
.background(Color.white,in: RoundedRectangle(cornerRadius: 10, style: .continuous))
.shadow(color: .black.opacity(0.1), radius: 5, x: 5, y: 5)
}
Text(trouserData.trouser_name)
.font(.largeTitle)
.fontWeight(.heavy)
.foregroundColor(.black)
}
VStack(spacing: 10){
WebImage(url: URL(string: trouserData.trouser_image))
.resizable()
.aspectRatio(contentMode: .fill)
.edgesIgnoringSafeArea(.all)
.cornerRadius(15)
Text("Details")
.opacity(0.7)
.frame(maxWidth: .infinity,alignment: .leading)
.padding(.bottom)
HStack(spacing: 15) {
Text(trouserData.trouser_details)
.font(.system(size: 18))
.padding()
}
}
}
}
Code for the SharedDataModel:
class SharedDataModel: ObservableObject {
// Detail Shirt Data...
@Published var detailShirt : Shirt?
@Published var showDetailShirt : Bool = false
// matched Geoemtry Effect from Search page...
@Published var fromSearchPage: Bool = false
}
The updated code for marketplace:
@Binding var charityData : Charity!
@Binding var showDetailCharity: Bool
@Binding var businessData : Business!
@Binding var showDetailBusiness: Bool
var body: some View {
ScrollView(.vertical, showsIndicators: false) {
VStack(spacing: 10){
if !showDetailCharity && !showDetailBusiness {
//MARK: This is the filter bar - the view for this is further down the page
marketplaceFilterBar
}
if selectedMarketplaceFilter == .raise {
MarketplaceRaiseView()
}
if selectedMarketplaceFilter == .save {
MarketplaceSaveView()
}
}
The code for TabView:
@StateObject var appModel: AppViewModel = .init()
@StateObject var sharedData: SharedDataModel = SharedDataModel()
// Animation Namespace...
@Namespace var animation
// Hiding Tab Bar...
init(){
UITabBar.appearance().isHidden = true
}
var body: some View {
VStack(spacing: 0){
// Tab View...
TabView(selection: $appModel.currentTab) {
Marketplace(animation: _animation)
.environmentObject(sharedData)
.tag(Tab.Market)
.setUpTab()
Home()
.environmentObject(sharedData)
.tag(Tab.Home)
.setUpTab()
}