I have a list of cars with a toggle button next to each car. There is also a SearchBar at top. Currently, toogle works fine when search bar is empty. When I type something in search bar, it neither filters the list nor toggle maintains its position. How can I maintain toggle position for each car when list is filtered?
For instance, if I select top three cars without search text. Now I start typing in the search bar, top three toggles remain enabled.
struct Car: Identifiable {
var id = UUID()
var name: String
var selected: Bool = false
}
struct ContentView: View {
@State var cars = [Car(name: "Subaru WRX", selected: false), Car(name:"Tesla Model 3",selected: false), Car(name:"Porsche 911 sjfnewif ewihf dwehifiw eufhwueif uhewfuwe u",selected: false), Car(name:"Renault Zoe",selected: false), Car(name:"DeLorean",selected: false), Car(name:"Mitsubishi Lancer",selected: false), Car(name:"Audi RS6", selected:false),Car(name:"Subaru WRX",selected: false), Car(name:"Tesla Model 3",selected: false), Car(name:"Porsche 911",selected: false), Car(name:"Renault Zoe",selected: false), Car(name:"DeLorean",selected: false), Car(name:"Mitsubishi Lancer",selected: false), Car(name:"Audi RS6", selected:false),
Car(name:"Subaru WRX",selected: false), Car(name:"Tesla Model 3",selected: false), Car(name:"Porsche 911",selected: false), Car(name:"Renault Zoe",selected: false), Car(name:"DeLorean",selected: false), Car(name:"Mitsubishi Lancer",selected: false), Car(name:"Audi RS6",selected:false),
Car(name:"Subaru WRX",selected: false), Car(name:"Tesla Model 3",selected: false), Car(name:"Porsche 911",selected: false), Car(name:"Renault Zoe",selected: false), Car(name:"DeLorean",selected: false), Car(name:"Mitsubishi Lancer",selected: false), Car(name:"Audi RS6", selected:false),
Car(name:"Subaru WRX",selected: false), Car(name:"Tesla Model 3",selected: false), Car(name:"Porsche 911",selected: false), Car(name:"Renault Zoe",selected: false), Car(name:"DeLorean",selected: false), Car(name:"Mitsubishi Lancer",selected: false), Car(name:"Audi RS6", selected: false)]
@State var showAlert = false
@State private var searchText : String = ""
var body: some View {
NavigationView{
VStack {
ScrollView {
VStack (alignment: .leading) {
SearchBar(text: $searchText, placeholder: "Car name")
Button(action: {
self.showAlert = true
print("Button tapped!")
}) {
Text("Browse by category").foregroundColor(Color.black).padding(.leading).font(.system(size: 15))
}.alert(isPresented: $showAlert) {
Alert(title: Text("Your Score"), message: Text("\(self.searchText)"))
}
ForEach(self.cars.filter {
self.searchText.isEmpty ? true : $0.name.lowercased().contains(self.searchText.lowercased())
}.indices, id: \.self) { idx in
ZStack (alignment: .leading) {
RoundedRectangle(cornerRadius: 5, style: .continuous)
.fill(Color.white).shadow(color:.green, radius: 5).padding(.leading).padding(.trailing)
HStack {
VStack (alignment: .leading) {
Text(self.cars[idx].name)
CatalogAvailable()
}.padding(.leading).padding(.trailing)
Toggle(isOn: self.$cars[idx].selected) {
Text("")
}.toggleStyle(CheckboxToggleStyle()).labelsHidden()
.frame(width: 10, height: 10, alignment: .trailing).padding()
}.padding().frame(maxWidth: .infinity, alignment: .leading)
}.onTapGesture {
self.cars[idx].selected.toggle()
}
}
}
}.navigationBarTitle("Add your cars")
Button(action: {
print("Button tapped!")
}) {
Text("Next")
}.padding(.bottom)
}
}
}
}
You iterate over indices
but after filtering they do not correspond to original array, but just ordered indices of filtered array. You have to work with id
of cars instead
Here is a sketch of idea:
ForEach(self.cars.filter {
self.searchText.isEmpty ? true : $0.name.lowercased().contains(self.searchText.lowercased())
}) { car in
self.row(for: car)
}
...
func row(for car: Car) -> some View {
let idx = self.cars.firstIndex(of car)!
return ZStack (alignment: .leading) {
RoundedRectangle(cornerRadius: 5, style: .continuous)
.fill(Color.white).shadow(color:.green, radius: 5).padding(.leading).padding(.trailing)
HStack {
VStack (alignment: .leading) {
Text(self.cars[idx].name)
CatalogAvailable()
}.padding(.leading).padding(.trailing)
Toggle(isOn: self.$cars[idx].selected) {
Text("")
}.toggleStyle(CheckboxToggleStyle()).labelsHidden()
.frame(width: 10, height: 10, alignment: .trailing).padding()
}.padding().frame(maxWidth: .infinity, alignment: .leading)
}.onTapGesture {
self.cars[idx].selected.toggle()
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.