Skip to main content

Dynamisches Filtermenü

Beschreibung

Diese View bietet ein dynamisches Filtermenü, mit dem Nutzer Inhalte anhand mehrerer Kriterien wie Checkboxen und Schieberegler in Echtzeit filtern können. Die Ergebnisse werden sofort aktualisiert, sobald Filteroptionen verändert werden.

🔍 Zweck

  • Produktsuche in Online-Shops nach Kategorie und Preisbereich filtern
  • Immobilienangebote nach Ausstattung und Preis selektieren
  • Musikbibliotheken nach Genre und Erscheinungsjahr eingrenzen
  • Rezeptdatenbanken nach Zutaten und Schwierigkeitsgrad filtern
  • Veranstaltungslisten nach Datum und Ort sortieren

📄 Codebeispiel

import SwiftUI

struct Item: Identifiable {
    let id = UUID()
    let name: String
    let category: String
    let price: Double
}

struct DynamicFilterMenuView: View {
    // Sample data set
    private let items = [
        Item(name: "MacBook Air", category: "Electronics", price: 1200),
        Item(name: "Sessel Modern", category: "Furniture", price: 350),
        Item(name: "Kopfhörer Pro", category: "Electronics", price: 199),
        Item(name: "Stehlampe Vintage", category: "Furniture", price: 120),
        Item(name: "Smartphone XL", category: "Electronics", price: 900),
        Item(name: "Esstisch Holz", category: "Furniture", price: 750),
        Item(name: "Bluetooth Speaker", category: "Electronics", price: 99),
        Item(name: "Bücherregal Weiß", category: "Furniture", price: 230),
    ]
    
    // Filter states
    @State private var showElectronics = true
    @State private var showFurniture = true
    @State private var maxPrice = 1300.0
    
    var filteredItems: [Item] {
        items.filter { item in
            ((showElectronics && item.category == "Electronics") ||
             (showFurniture && item.category == "Furniture"))
            && item.price <= maxPrice
        }
    }
    
    var body: some View {
        NavigationStack {
            VStack(alignment:.leading) {
                // Filter Menu Section
                VStack(alignment:.leading, spacing:.zero) {
                    HStack(alignment:.center) {
                        Image(systemName:"line.3.horizontal.decrease.circle")
                            .foregroundColor(.accentColor)
                        Text("Filter")
                            .font(.headline)
                    }
                    Divider().padding(.bottom, 4)

                    Toggle(isOn:$showElectronics) {
                        Label("Elektronik", systemImage:"bolt.fill")
                    }.toggleStyle(.switch)

                    Toggle(isOn:$showFurniture) {
                        Label("Möbel", systemImage:"bed.double.fill")
                    }.toggleStyle(.switch)

                    VStack(alignment:.leading) {
                        Text("Maximaler Preis (\(Int(maxPrice)) €)")
                            .font(.subheadline)
                        Slider(value:$maxPrice,
                               in:(50...1300),
                               step:(50)) { editing in } minimumValueLabel:{ Text("50") } maximumValueLabel:{ Text("1300") }
                    }.padding(.top,6)

                    Divider().padding([.top,.bottom],8)
                }
                .padding()
                .background(Color(.systemGray6))
                .cornerRadius(12)

                // Results Section
                Text("\(filteredItems.count) Ergebnis(se)")
                    .font(.headline)
                    .padding([.top,.bottom],4)

                List(filteredItems) { item in
                    HStack(spacing:.zero) {
                        VStack(alignment:.leading) {
                            Text(item.name).fontWeight(.medium)
                            Text(item.category).font(.caption).foregroundColor(.secondary)
                        }
                        Spacer()
                        Text(String(format:"%.0f €",item.price))
                            .fontWeight(.semibold)
                            .foregroundColor(item.category == "Electronics" ? Color.blue : Color.orange)
                    }.padding([.vertical],2)
                }.listStyle(.plain)

                Spacer()
            }
            .navigationTitle("Dynamisches Filtermenü")
            .padding()
        }
    }
}

#Preview {
    DynamicFilterMenuView()
}