Home > front end >  Turn Button into Picker
Turn Button into Picker

Time:04-13

I have this code, where there are three buttons which have values stored in each of them.

When I press the Add button, the values add up and appear on the list. However, I am not able to check which values are being selected.

How can I make the button look like a picker, so that when the user clicks the button A, B, or C, it will show with a checkmark that it has been selected and when the user taps the Add button, the value of the selected button and "gp" should show up on the list? Also, the checkmark should disappear once the Add button is selected so that the user can select another list.

Such as:

  • If A and B are selected, the list should look like:

A = 2.0, B = 5.0, gp = 7.0.

  • If A and C are selected, the list should look like:

A= 2.0, C = 7.0, gp = 9.0.

I have tried using Picker and other methods, however, I couldn't get through. I have found this as the best solution. However, I am not able to put a checkmark on the buttons and not able to show the selected values on the list.

import SwiftUI

struct MainView: View {

    @State var br = Double()
    @State var loadpay = Double()
    @State var gp : Double = 0
    @State var count: Int = 1
    @State var listcheck = Bool()
    @StateObject var taskStore = TaskStore()
    @State var a = 2.0
    @State var b = 5.0
    @State var c = 7.0
   
    //var userCasual = UserDefaults.standard.value(forKey: "userCasual") as? String ?? ""
    @State var name = String()
   
    func addNewToDo() {
       taskStore.tasks.append(Task(id: String(taskStore.tasks.count   1), toDoItem:  "load \(gp)", amount: Double(gp)))
       self.gp = 0.0
    }

    func stepcount() {
       count  = 1
    }

    var body: some View {
        HStack {
            Button(action: { gp  = a }) {
               Text("A =").frame(width: 70, height: 15)
                  .foregroundColor(.yellow)
            }  
            .background(RoundedRectangle(cornerRadius: 5))
            .foregroundColor(.black)

            Button(action: { gp  = b }) {
               Text("B =") .frame(width: 70, height: 15)
                  .foregroundColor(.yellow)
            }
            .background(RoundedRectangle(cornerRadius: 5))
            .foregroundColor(.black)

            Button(action: { gp  = c }) {
               Text("C =").frame(width: 70, height: 15)
                  .foregroundColor(.yellow)
             }
             .background(RoundedRectangle(cornerRadius: 5))
             .foregroundColor(.black)
        }

        HStack(spacing: 15) { 
           Button(
              String(format: ""), 
              action: { 
                 print("pay for the shift is ")
                 gp  = loadpay
              }
           )

           Button(
              action: {
                 addNewToDo()
                 stepcount()
              },  
              label: { Text("Add")}
           )
        }

     Form {
        ForEach(self.taskStore.tasks) { task in
            Text(task.toDoItem)
        }
     }
   }
}

struct Task : Codable, Identifiable {
    var id = ""
    var toDoItem = ""
    var amount = 0.0
}

class TaskStore : ObservableObject {
    @Published var tasks = [Task]()
}

CodePudding user response:

The issue is you are trying to turn a Button into something it is not. You can create your own view that responds to a tap and keeps its state so it knows whether it is currently selected or not. An example is this:

struct MultiPickerView: View {
    
    @State private var selectA = false
    @State private var selectB = false
    @State private var selectC = false
    
    let A = 2.0
    let B = 5.0
    let C = 7.0
    
    var gp: Double {
        (selectA ? A : 0)   (selectB ? B : 0)   (selectC ? C : 0)
    }
    
    var body: some View {
        VStack {
            HStack {
                SelectionButton(title: "A", selection: $selectA)
                SelectionButton(title: "B", selection: $selectB)
                SelectionButton(title: "C", selection: $selectC)
            }
            .foregroundColor(.blue)
            Text(gp.description)
                .padding()
        }
    }
}

struct SelectionButton: View {

    let title: String
    @Binding var selection: Bool
    
    var body: some View {
        HStack {
            Image(systemName: selection ? "checkmark.circle" : "circle")
            Text(title)
        }
        .padding()
        .overlay(
            RoundedRectangle(cornerRadius: 15)
                .stroke(Color.blue, lineWidth: 4)
        )
        .padding()
        .onTapGesture {
            selection.toggle()
        }

    }
}

You could make it more adaptable by using an Array that has a struct that keeps the value and selected state, and run it though a ForEach, but this is the basics of the logic.

  • Related