当按下按钮并切换 Bool var 时,我的 Bool vars 是否会切换?

时间:2021-04-13 04:04:38

标签: swift forms swiftui state

我有一个包含多个布尔变量的表单,可以在切换时更改图像,但是当我单击任何按钮时,所有变量都会更改图像?我已将它们全部拉入具有相同结果的单独子视图中。对我来说没有任何意义。任何帮助,将不胜感激。可能我忽略了一些简单的东西,但如果我能看到它,我会被诅咒。

这是代码。

@State var total: String = ""
@State var date: Date = Date()
@State var bathroom: Bool = false
@State var steps: Bool = false
@State var furniture: Bool = false
@State var travel: Bool = false
@State var woodFloor: Bool = false
@State var concreteFloor: Bool = false
@State var takeUp: Bool = false

var body: some View {
    VStack {
        Form {
            Section(header: Text("Job Info")
                .font(.title2)
                .foregroundColor(.blue)
                .fontWeight(.bold)
                .padding(.bottom, 10)
            ) {
                VStack(alignment: .leading) {
                    DatePicker("Date", selection: $date)
                        .font(.title3)
                        .foregroundColor(.black)
                        .padding(.bottom, 10)
                    HStack(alignment: .center) {
                        Text("Total: $")
                            .font(.title3)
                            .foregroundColor(.black)
                            .padding(.trailing, 0)
                        TextField("", text: $total)
                            .font(.title3)
                            .frame(width: 100, height: 20, alignment: .leading)
                            .background(Color.yellow)
                            .foregroundColor(.black)
                            .cornerRadius(5)
                        Spacer()
                    }
                    .padding(.bottom, 20)
                }

                Section(header: Text("Addons")
                    .font(.title3)
                    .foregroundColor(.blue)
                    .padding(.bottom, 10)
                ) {
                    VStack(alignment: .leading, spacing: 5) {
                        Spacer()
                        HStack {
                            Text("Bathroom")
                            Spacer()
                            Button {
                                self.bathroom.toggle()
                            } label: {
                                Image(systemName: bathroom ? "checkmark.square" : "square")
                           }
                        }
                        
                        HStack {
                            Text("Steps")
                            Spacer()
                            Button {
                                self.steps.toggle()
                            } label: {
                                Image(systemName: steps ? "checkmark.square" : "square")
                            }
                        }

                        HStack {
                            Text("Furniture")
                            Spacer()
                            Button {
                                self.furniture.toggle()
                            } label: {
                                Image(systemName: furniture ? "checkmark.square" : "square")
                            }
                        }
                        Spacer()
                    }
                }
            }
        }

3 个答案:

答案 0 :(得分:1)

您将所有按钮放在一行中(VStackHStacks 创建一个视图,因此为一行),并且 Form(作为 List)在任何时候发送所有操作在一行中单击任何按钮(它被设计为在一行中有一个活动元素)。

所以解决方案要么是删除 VStack

Section(header: Text("Addons")
    .font(.title3)
    .foregroundColor(.blue)
    .padding(.bottom, 10)
) {
    VStack(alignment: .leading, spacing: 5) {      // << this !!
        Spacer()

并让每个带有按钮的 HStack 位于自己的行中...

... 或者使用带有点击手势的 Image 代替按钮,例如

    HStack {
        Text("Steps")
        Spacer()
        Image(systemName: steps ? "checkmark.square" : "square")
          .padding()
          .onTapGesture {
            self.steps.toggle()
          }
    }

答案 1 :(得分:0)

如果您在 SectionForm 中有一个按钮,则整个部分将充当按钮。因此,当您点击它时,所有 3 个按钮操作都会执行。

相反,您可以将 Image.onTapGesture{} 修饰符一起使用。这样,你就会得到你想要的。

示例代码,

 Image(systemName: bathroom ? "checkmark.square" : "square")
   .foregroundColor(.blue)
   .onTapGesture {
      self.bathroom.toggle()
   }

答案 2 :(得分:0)

我认为您对 Form 的期望是错误的。 Form 不要用花哨的东西制作灵活的列表。如果您希望能够做任何您想做的事情并能够随意自定义您的列表,您可能应该使用 Grid 和其他普通组件,例如 VStack...

如何使用 Form 以及期待什么:

在不解决这些限制的情况下,查看您可以使用 Form 做什么或不可以做什么的最简单方法是转到 iPhone 上的设置,查看设置的不同部分是如何进行的。您可以非常轻松地实现几乎所有这些目标,无需太多工作。但是,如果您想要一些与您在设置中看到的有所不同的东西,那么您可能需要一种解决方法来在您的应用中实现它,因为 Form 不灵活。
从设置中获取的 Form 可以做什么的示例: enter image description here

为了澄清起见,我并不是说您无法使用表单实现您想要的目标。我的意思是,试图强迫表单成为它们不应该成为的东西,这很可能不是一个好主意。

答案:

那你现在该怎么办?您可能应该用 Toggle 替换您的按钮,以便获得与您在设置中看到的类似的内容。
[其他人已经说过如何解决您当前的问题,所以我只说更好的方法]
考虑使用这样的东西:

struct ContentView: View {
    
    @State var date = Date()
    @State var total = ""
    @State var bathroom = false
    @State var steps = false
    @State var furniture = false
    
    var body: some View {
        NavigationView { // DELETE this if the view before this view
                         // already has a navigation view
            Form {
                Section(header: Text("Job Info")) {
                    DatePicker("Date", selection: $date)
                    NavigationLink.init(
                        destination: FormTextFieldView(name: "Total $", value: $total),
                        label: {
                            Text("Total")
                            Spacer()
                            Text("$ " + total).foregroundColor(.secondary)
                        })
                }
                
                Section(header: Text("Addons")) {
                    Toggle("Bathroom", isOn: $bathroom)
                    Toggle("Steps", isOn: $steps)
                    Toggle("Furniture", isOn: $furniture)
                }
            }
            .navigationBarTitle("Form", displayMode: .inline)
        }
    }
}

struct FormTextFieldView: View {
    
    let name: String
    @Binding var value: String
    
    var body: some View {
        Form {
            TextField(name, text: $value)
        }
        .navigationBarTitle(name)
    }
}

为什么要使用这个?

首先,因为它是在毫不费力的情况下构建的。您几乎不需要使用任何修饰符。这么简单!
其次,这将适用于任何苹果设备。当您使用修饰符时,特别是为视图设置框架时,您需要考虑如果使用例如一个 iPad。当您使用这种方法时,您无需担心这一点。