'Why is ForEach not changing my Foreground color correctly in SwiftUI?
I am trying to make a simple Todo app and I'm trying to implement a feature where if I click on a row, the foreground color will be change. However, I have two problems, first when I toggle the boolean value in for my core data attribute, nothing happens on the front end. The value changes true/false but the foreground color is not changing.
Second, when I instead use a simple @State boolean value, ALL the list row foreground colors change instead of just the row I tapped on.
import SwiftUI
import ChameleonFramework
struct ItemView: View {
@Environment(\.managedObjectContext) private var moc
@StateObject var category: Category
@State private var showAddItemView = false
@State private var text = ""
@State var testBool = false
var body: some View {
NavigationView {
VStack {
List {
ForEach(searchResults) { item in
Text(item.unwrappedTitle)
.foregroundColor(item.unwrappedDone ? .red : .blue)
// .foregroundColor(Color(ContrastColorOf(backgroundColor: UIColor(hexString: category.unwrappedColor), returnFlat: true)))
.onTapGesture {
print(item.unwrappedTitle)
item.done.toggle()
print(item.done)
try? moc.save()
}
.listRowBackground(Color(UIColor(hexString: category.unwrappedColor)))
// .listRowBackground(Color(UIColor(hexString: category.unwrappedColor).darken(byPercentage: 0.5)))
// .listRowBackground(Color(HexColor(hexString: category.unwrappedColor)))
}
So using the Core Data variable item.done.toggle
does nothing to change the foreground color when toggled but it does switch between true/false. Alternatively, using the @State var testBool
changes ALL the rows instead of just the one tapped.
I want to tap on a row and have it change color on only that row.
I made searchResults
equal to category.itemArray
for purposes of search and filtering.
var searchResults: [Item] {
if text.isEmpty {
return category.itemArray
} else {
return category.itemArray.filter { Item in
Item.title!.lowercased().contains(text.lowercased())
}
}
}
Solution 1:[1]
So I asked another question using mock data on another post and that helped me solve this. Basically, I just needed to make a subview
struct ExtractedView: View {
@Environment(\.managedObjectContext) private var moc
@State var testBool = false
let item: Item
var body: some View {
Text(item.unwrappedTitle)
.foregroundColor(testBool ? .red : .green)
.foregroundColor(Color(ContrastColorOf(backgroundColor: UIColor(hexString: item.unwrappedColor), returnFlat: true)))
.onTapGesture {
print(item.unwrappedTitle)
item.done.toggle()
print(item.unwrappedDone)
testBool.toggle()
try? moc.save()
}
.listRowBackground(Color(UIColor(hexString: item.unwrappedColor)))
}
}
And here is the ExtractedView using ForEach..
import SwiftUI
import ChameleonFramework
struct ItemView: View {
@Environment(\.managedObjectContext) private var moc
@StateObject var category: Category
@State private var showAddItemView = false
@State private var text = ""
// @State var testBool = false
var body: some View {
NavigationView {
VStack {
List {
ForEach(searchResults) { item in
ExtractedView(item: item)
// .listRowBackground(Color(UIColor(hexString: category.unwrappedColor).darken(byPercentage: 0.5)))
// .listRowBackground(Color(HexColor(hexString: category.unwrappedColor)))
}
.onDelete(perform: deleteItem)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Tomas |