简体   繁体   中英

SwiftUI: Manipulate single Items generated from "For - In" loop

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"),
            
        ]
    }
}

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)

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
}

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)

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM