You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 14:50:30