我正在嘗試為用戶選擇的每張食物圖片添加一個復選標記,但它會在每個選項上都被選中,而不僅僅是一個。
我知道這ForEach可能是造成這種情況的原因。但我想不出辦法來解決這個問題。
模擬器上的問題。
ScrollView(.horizontal, showsIndicators: false) {
HStack(alignment: .bottom) {
ForEach(comidas) { comida in
VStack(alignment: .center) {
ZStack(alignment: .center) {
Image(uiImage: comida.foodImage)
.resizable()
.blur(radius: 2)
.frame(width: 200, height: 200)
.cornerRadius(10)
.onTapGesture {
withAnimation {
isChecked.toggle()
}
}
Text(comida.name)
.font(.title2)
.fontWeight(.bold)
.foregroundColor(.white)
Image(systemName: "checkmark.circle")
.resizable()
.aspectRatio(contentMode: .fit)
.foregroundColor(Color.white)
.frame(width: 100, height: 100)
.opacity(isChecked ? 1 : 0 )
.animation(.easeIn(duration: 0.5))
}
}
.padding(.horizontal, 3)
}
}
}
//"comidas" is food in Spanish
struct Comidas: Identifiable {
var id: Int
let name: String
let foodImage: UIImage
}
let comidas = [
Comidas(id: 0, name: "Asado", foodImage: UIImage(imageLiteralResourceName: "asado")),
Comidas(id: 1, name: "Pizzas", foodImage: UIImage(imageLiteralResourceName: "pizzas")),
Comidas(id: 2, name: "Milanesas", foodImage: UIImage(imageLiteralResourceName: "milanesas")),
Comidas(id: 3, name: "Empanadas", foodImage: UIImage(imageLiteralResourceName: "empanadas")),
Comidas(id: 4, name: "Pastas", foodImage: UIImage(imageLiteralResourceName: "pasta")),
Comidas(id: 5, name: "Sushi", foodImage: UIImage(imageLiteralResourceName: "sushi")),
Comidas(id: 6, name: "Facturas", foodImage: UIImage(imageLiteralResourceName: "facturas")),
Comidas(id: 7, name: "Café", foodImage: UIImage(imageLiteralResourceName: "cafe")),
Comidas(id: 8, name: "Helados", foodImage: UIImage(imageLiteralResourceName: "helados"))
]
uj5u.com熱心網友回復:
保留所選 comidas 的參考并使用它來確定 comida 的檢查狀態。我更喜歡Set在這種情況下使用 a ,因為它會自動處理重復項并簡化添加/洗掉專案。
首先是添加Hashable一致性,Comida以便我們可以Set使用它進行操作。結構內的所有屬性都Comida已經符合,因此您只需要Hashable宣告符合性。Hashable
//note that comida should be singular since it represents a single item
struct Comida: Identifiable, Hashable {
在您看來,添加一個@State變數來跟蹤用戶選擇Comida的 s
@State var comidasEligidas: Set<Comida> = []
在您對 comida 的點擊手勢中Image,從comidasEligidas Set
.onTapGesture {
if comidasEligidas.contains(comida) {
comidasEligidas.remove(comida)
} else {
comidasEligidas.insert(comida)
}
}
根據集合中是否存在 來切換復選標記的不透明度Comida,并指示要觀察影片的值是eligidasComidas Set。另外,我建議禁用hitTesting復選標記,以免它吞下任何觸摸。
.opacity(comidasEligidas.contains(comida) ? 1 : 0 )
.animation(.easeIn(duration: 0.5), value: comidasEligidas)
.allowsHitTesting(false)
這是完整的代碼片段:
struct ContentView: View {
struct Comida: Identifiable, Hashable {
var id: Int
let name: String
let foodImage: UIImage
}
let comidas = [
Comida(id: 0, name: "Asado", foodImage: UIImage(imageLiteralResourceName: "asado")),
Comida(id: 1, name: "Pizzas", foodImage: UIImage(imageLiteralResourceName: "pizzas")),
Comida(id: 2, name: "Milanesas", foodImage: UIImage(imageLiteralResourceName: "milanesas")),
Comida(id: 3, name: "Empanadas", foodImage: UIImage(imageLiteralResourceName: "empanadas")),
Comida(id: 4, name: "Pastas", foodImage: UIImage(imageLiteralResourceName: "pasta")),
Comida(id: 5, name: "Sushi", foodImage: UIImage(imageLiteralResourceName: "sushi")),
Comida(id: 6, name: "Facturas", foodImage: UIImage(imageLiteralResourceName: "facturas")),
Comida(id: 7, name: "Café", foodImage: UIImage(imageLiteralResourceName: "cafe")),
Comida(id: 8, name: "Helados", foodImage: UIImage(imageLiteralResourceName: "helados"))
]
@State var comidasEligidas: Set<Comida> = []
var body: some View {
ScrollView(.horizontal, showsIndicators: false) {
HStack(alignment: .bottom) {
ForEach(comidas) { comida in
VStack(alignment: .center) {
ZStack(alignment: .center) {
Image(uiImage: comida.foodImage)
.resizable()
.blur(radius: 2)
.frame(width: 200, height: 200)
.cornerRadius(10)
.onTapGesture {
if comidasEligidas.contains(comida) {
comidasEligidas.remove(comida)
} else {
comidasEligidas.insert(comida)
}
}
Text(comida.name)
.font(.title2)
.fontWeight(.bold)
.foregroundColor(.white)
Image(systemName: "checkmark.circle")
.resizable()
.aspectRatio(contentMode: .fit)
.foregroundColor(Color.white)
.frame(width: 100, height: 100)
.opacity(comidasEligidas.contains(comida) ? 1 : 0 )
.animation(.easeIn(duration: 0.5), value: comidasEligidas)
.allowsHitTesting(false)
}
}
.padding(.horizontal, 3)
}
}
}
}
}
uj5u.com熱心網友回復:
您可以嘗試這種方法,ObservableObject在您的 comidas 陣列中使用 a var isChecked,在Comidas結構中使用 a。這對我很有效。
struct ContentView: View {
@StateObject var comidasModel = ComidasModel() // <-- here
var body: some View {
ScrollView(.horizontal, showsIndicators: false) {
HStack(alignment: .bottom) {
ForEach(comidasModel.comidas) { comida in // <-- here
VStack(alignment: .center) {
ZStack(alignment: .center) {
Image(uiImage: comida.foodImage)
.resizable()
.blur(radius: 2)
.frame(width: 200, height: 200)
.cornerRadius(10)
.onTapGesture {
withAnimation {
comidasModel.toggleChecked(for: comida) // <-- here
}
}
Text(comida.name)
.font(.title2)
.fontWeight(.bold)
.foregroundColor(.white)
Image(systemName: "checkmark.circle")
.resizable()
.aspectRatio(contentMode: .fit)
.foregroundColor(Color.white)
.frame(width: 100, height: 100)
.opacity(comida.isChecked ? 1 : 0 )
.animation(.easeIn(duration: 0.5))
// enable click on the checkmark circle
.onTapGesture {
withAnimation {
comidasModel.toggleChecked(for: comida)
}
}
}
}
.padding(.horizontal, 3)
}
}
}
}
}
class ComidasModel: ObservableObject {
@Published var comidas = [
Comidas(id: 0, name: "Asado", foodImage: UIImage(imageLiteralResourceName: "asado")),
Comidas(id: 1, name: "Pizzas", foodImage: UIImage(imageLiteralResourceName: "pizzas")),
Comidas(id: 2, name: "Milanesas", foodImage: UIImage(imageLiteralResourceName: "milanesas")),
Comidas(id: 3, name: "Empanadas", foodImage: UIImage(imageLiteralResourceName: "empanadas")),
Comidas(id: 4, name: "Pastas", foodImage: UIImage(imageLiteralResourceName: "pasta")),
Comidas(id: 5, name: "Sushi", foodImage: UIImage(imageLiteralResourceName: "sushi")),
Comidas(id: 6, name: "Facturas", foodImage: UIImage(imageLiteralResourceName: "facturas")),
Comidas(id: 7, name: "Café", foodImage: UIImage(imageLiteralResourceName: "cafe")),
Comidas(id: 8, name: "Helados", foodImage: UIImage(imageLiteralResourceName: "helados"))
]
func toggleChecked(for comida: Comidas) {
if let ndx = comidas.firstIndex(of: comida) {
comidas[ndx].isChecked.toggle()
}
}
}
struct Comidas: Identifiable, Equatable {
var id: Int
var isChecked: Bool = false // <-- here
let name: String
let foodImage: UIImage
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/440612.html
