SwiftUI实现答题按钮点击后仅改变自身背景色的方法
问题:修改SwiftUI测验应用按钮背景色逻辑
我正在开发一款测验应用,现有两段SwiftUI视图代码。目前答对/答错时会改变整个屏幕背景色(正确为绿色,错误为红色),但我希望仅改变点击的按钮背景色,屏幕背景保持白色。请指导如何修改代码?
原ContentView代码
import SwiftUI struct ContentView: View { let question = Question(questionText: "What was the first computer bug?", possibleAnswers: ["Ant", "Beetle", "Moth", "Fly"], correctAnswerIndex: 2) @State var mainColor = Color(red: 255/255, green: 255/255, blue: 255/255) @State var textBackgroundColor = Color.white var body: some View { ZStack { mainColor.ignoresSafeArea() VStack{ Text("Question 1 of 10") .font(.callout) .foregroundColor(.gray) .padding(.bottom, 1) .padding(.trailing, 170) .multilineTextAlignment(.leading) Text(question.questionText) .font(.largeTitle) .multilineTextAlignment(.leading) .bold() .background(textBackgroundColor) Spacer() .frame(height: 200) VStack(spacing: 20){ ForEach(0..<question.possibleAnswers.count) { answerIndex in Button(action: { print("Tapped on option with the text: \(question.possibleAnswers[answerIndex])") mainColor = answerIndex == question.correctAnswerIndex ? .green : .red textBackgroundColor = answerIndex == question.correctAnswerIndex ? .green : .red print(textBackgroundColor) }, label: { ChoiceTextView(choiceText: question.possibleAnswers[answerIndex]) }) } } } } } } struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() } }
原ChoiceTextView代码
import SwiftUI struct ChoiceTextView: View { let choiceText: String let accentColor = Color(red: 48/255, green: 105/255, blue: 240/255) @State var textBackgroundColor = Color.white var body: some View { Text(choiceText) .frame(width:250) .foregroundColor(.black) .padding() // make background white to put shadow later .background(textBackgroundColor) .cornerRadius(10) .shadow(color: Color(hue: 1.0, saturation: 0.0, brightness: 0.869), radius: 5, x: 0, y: 5) } } struct ChoiceTextView_Previews: PreviewProvider { static var previews: some View { ChoiceTextView(choiceText: "Choice Text!", textBackgroundColor: Color.white) } }
修改方案
核心思路是移除全局背景色控制,给每个选项单独维护点击后的背景状态,具体步骤如下:
1. 修改ContentView
- 删除控制全局背景的
mainColor和textBackgroundColor变量 - 添加
selectedAnswerIndex变量记录用户点击的选项索引 - 按钮点击时仅记录选中索引,不再修改全局颜色
- 给每个
ChoiceTextView传递动态背景色:选中时根据是否正确显示绿/红,未选中时保持白色
修改后的ContentView代码:
import SwiftUI struct ContentView: View { let question = Question(questionText: "What was the first computer bug?", possibleAnswers: ["Ant", "Beetle", "Moth", "Fly"], correctAnswerIndex: 2) // 记录用户点击的选项索引,nil表示未点击 @State private var selectedAnswerIndex: Int? var body: some View { ZStack { // 固定屏幕背景为白色 Color.white.ignoresSafeArea() VStack{ Text("Question 1 of 10") .font(.callout) .foregroundColor(.gray) .padding(.bottom, 1) .padding(.trailing, 170) .multilineTextAlignment(.leading) Text(question.questionText) .font(.largeTitle) .multilineTextAlignment(.leading) .bold() Spacer() .frame(height: 200) VStack(spacing: 20){ ForEach(0..<question.possibleAnswers.count) { answerIndex in Button(action: { print("Tapped on option with the text: \(question.possibleAnswers[answerIndex])") // 仅记录选中的选项索引 selectedAnswerIndex = answerIndex }, label: { // 根据选中状态和正确性设置按钮背景色 let bgColor: Color if let selectedIndex = selectedAnswerIndex, selectedIndex == answerIndex { bgColor = answerIndex == question.correctAnswerIndex ? .green : .red } else { bgColor = .white } ChoiceTextView(choiceText: question.possibleAnswers[answerIndex], textBackgroundColor: bgColor) }) } } } } } } struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() } }
2. 修改ChoiceTextView
- 将
@State var textBackgroundColor改为let,因为背景色由父视图控制,子视图无需自己维护状态 - 确保预览代码传递正确的参数
修改后的ChoiceTextView代码:
import SwiftUI struct ChoiceTextView: View { let choiceText: String let textBackgroundColor: Color // 改为let,由父视图传入 let accentColor = Color(red: 48/255, green: 105/255, blue: 240/255) var body: some View { Text(choiceText) .frame(width:250) .foregroundColor(.black) .padding() .background(textBackgroundColor) .cornerRadius(10) .shadow(color: Color(hue: 1.0, saturation: 0.0, brightness: 0.869), radius: 5, x: 0, y: 5) } } struct ChoiceTextView_Previews: PreviewProvider { static var previews: some View { ChoiceTextView(choiceText: "Choice Text!", textBackgroundColor: .white) } }
内容的提问来源于stack exchange,提问作者DezdaH
相关产品推荐
相关产品推荐

