SwiftUI: Manipulate single Items generated from “For - In” loop

强颜欢笑 提交于 2021-02-10 20:17:17

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!