问题
Aloha,
Introduction
The idea is to create a quiz game in which you have a varying amount of buttons, one answer is "right" the others are "wrong". When selecting any button the color of the "right button" should turn green, the rest turn red.
How the App works
The App loads all the data from a Swift file called LectureTopics (See Below). LectureTopics is a struct that contains a lot of variables (ButtonText, ButtoneAnswerCorrect (Bool) Descriptions etc.) and an extension that holds the content for those variabels (Level 1, 2 etc.)
Problem
I am creating several buttons with a "for in" loop (see below). However either all buttons turn red or green. The App already knows which button is wrong or right. For that I use the "Level0ButValue" variable (see below). However it should in theory only turn the right answer green and the others red. Would really appreciate any kinds of help. I am still new to programming :-) Thank you in advance!
struct Level0View: View {
let lectureTopic: LectureTopic
@State var Thacolor:String = "BlueAccent"
var body: some View {
VStack{
Text(lectureTopic.Level0Name)
.font(Font.custom("Arial", size: 24))
.multilineTextAlignment(.center)
.padding(.bottom)
.padding()
Text(lectureTopic.Level0Text)
.font(Font.custom("Arial", size: 18))
.multilineTextAlignment(.center)
.padding()
Text(lectureTopic.Level0Question)
.font(Font.custom("Arial", size: 22))
.fontWeight(.heavy)
Spacer()
VStack{
ForEach(0..<self.lectureTopic.Level0Buttons.count)
{ number in
Spacer()
Button(action:
{
if self.lectureTopic.Level0ButValue[number] == true
{
self.Thacolor = "GreenAccent"
}
else
{
self.Thacolor = "RedAccent"
}
})
{
Text(self.lectureTopic.Level0Buttons[number])
}
.foregroundColor(.white)
.padding()
.padding([.leading, .trailing])
.background(Color(self.Thacolor))
.cornerRadius(10)
}
Spacer()
Image("Window1")
.resizable()
.frame(width: 420, height: 190)
}
}
}
}
struct Level0View_Previews: PreviewProvider {
static var previews: some View {
Level0View(lectureTopic: LectureTopic.all()[0])
}
}
struct LectureTopic: Identifiable {
var id = UUID()
let LectureTitle: String
let MainMenuText: String
let MainImage: String
let OverviewText: String
let Level0Name: String
let Level0Text: String
let Level0Question: String
let Level0Buttons: [String]
let Level0ButValue: [Bool]
let Level1Name: String
let Level1Text: String
}
extension LectureTopic
{
static func all() -> [LectureTopic]
{
return
[
LectureTopic(
LectureTitle: "Basics",
MainMenuText: "Hier lernst du die Basics, von der Jobsuche bis hin zu allgemeinen Informationen.",
MainImage: "Window1",
OverviewText: "Nach drei Semestern studieren sucht Tim nach einer Möglichkeit erste, fachliche Berufserfahrung zu sammeln. Hierzu macht er sich auf die Suche nach einem Job den er neben dem Studium ausüben kann. ",
Level0Name: "Wie kann Tim?",
Level0Text: "Frage",
Level0Question: "Text11",
Level0Buttons: ["hi","Mu","Na"],
Level0ButValue: [true,false,false],
Level1Name: "alalal",
Level1Text: "Jojo"),
]
}
}
回答1:
Since you want to change the colors of all of the buttons as soon as one is selected, then you need a @State
variable that reflects that.
Add:
@State private var answered = false
Then your buttons will set self.answered = true
. The color of the button will depend on the state of answered
and self.lectureTopic.Level0ButValue[number]
:
Button(action:
{
self.answered = true
})
{
Text(self.lectureTopic.Level0Buttons[number])
}
.foregroundColor(.white)
.padding()
.padding([.leading, .trailing])
.background(Color(self.answered ? (self.lectureTopic.Level0ButValue[number] ? "GreenAccent" : "RedAccent") : "BlueAccent")))
.cornerRadius(10)
回答2:
i have prepared a more general example which is not directly related to your code but does exactly what you want to achieve. You could then apply this approach to your exact implementation. The important part is that there is now a second view just for the button that has its own @State
to control the color of the button.
import SwiftUI
struct ContentView: View {
let buttons = [ButtonData(text: "around 100", bool: false), ButtonData(text: "around 7.8 Billion", bool: true), ButtonData(text: "around 3712", bool: false)]
var body: some View {
VStack {
Text("what is the world population in 2020?")
ForEach(buttons) { buttonData in
ButtonView(buttonData: buttonData)
}
}
}
}
struct ButtonView: View {
let buttonData: ButtonData
@State private var color: Color = .primary
var body: some View {
Button {
if buttonData.bool {
color = .green
return
}
color = .red
} label: {
Text(buttonData.text)
.foregroundColor(color)
}
}
}
struct ButtonData: Identifiable {
let id = UUID()
let text: String
let bool: Bool
}
回答3:
I'll change the approach, instead of
.background(Color(self.Thacolor))
I'll have a bool (rightAnswer:Bool) a change the color according to the answer
.background(rightAnser: .blue ? .red)
来源:https://stackoverflow.com/questions/64497666/swiftui-manipulate-single-items-generated-from-for-in-loop