Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SwiftUI - How to change the colour of all other buttons when pressing on button?

Tags:

ios

swift

swiftui

Below in my code I have a setup where there are 4 Buttons, each time I press a button it acts as a toggle (like a radio button). What I would like to achieve is to turn all other buttons grey when pressing on one of the buttons. Only one button can be green or active at a time.

struct hzButton: View {
  var text: String
  @State var didTap: Bool

  var body: some View {
    Button(action: {
      if self.didTap == true{
        self.didTap = false
      }else{
        self.didTap = true
      }
      selectFreq(frequency: self.text)
    }) {
      Text(text)
        .font(.body)
        .fontWeight(.semibold)
        .foregroundColor(Color.white)
        .multilineTextAlignment(.center)
        .padding(.all)
        .background(didTap ? Color.green : Color.gray)
        .cornerRadius(6.0)
    }
    .frame(width: nil)
  }
}

struct Row: Identifiable {
  let id = UUID()
  let headline: String
  let numbers: [String]
}

struct ContentView: View {
  var rows = [
    Row(headline: "", numbers: ["250","500","750","1000"]),
  ]
  var body: some View {
    HStack {
      ForEach(rows) { row in
        HStack {
          ForEach(row.numbers, id: \.self) { text in
            hzButton(text: text, didTap: false)
          }
        }
      }
    }
  }
}
like image 264
Luke Ireton Avatar asked Dec 22 '22 20:12

Luke Ireton


2 Answers

In SwiftUI everything is triggered by a state change. To implement a radio-button style change you'll need to do something like:

struct MyRadioButton: View {
    let id: Int
    @Binding var currentlySelectedId: Int
    var body: some View {
        Button(action: { self.currentlySelectedId = self.id }, label: { Text("Tap Me!") })
            .foregroundColor(id == currentlySelectedId ? .green : .red)
    }
}


struct MyRadioButtons: View {
    @State var currentlySelectedId: Int = 0
    var body: some View {
        VStack {
            MyRadioButton(id: 1, currentlySelectedId: $currentlySelectedId)
            MyRadioButton(id: 2, currentlySelectedId: $currentlySelectedId)
            MyRadioButton(id: 3, currentlySelectedId: $currentlySelectedId)
            MyRadioButton(id: 4, currentlySelectedId: $currentlySelectedId)
        }
    }
}

When the shared currentlySelectedId changes, all buttons dependent on that state will update accordingly.

like image 159
Michael Long Avatar answered Feb 01 '23 22:02

Michael Long


Instead of thinking about it as 4 separate buttons, each with their own on/off state, think about the group as a whole and how they represent a single current-value state. Then, when each button is determining its background color, it can consider "does my value match the currently-selected value?". So instead of toggling a boolean when a button is tapped, have the button update the currently-selected value (shared among all buttons in the group) with its own value.

like image 38
Brian Avatar answered Feb 02 '23 00:02

Brian