How to uniquely get Button if I extract as a subview in SwiftUI

658 views Asked by At

So I am making a simple restaurant bill splitting app and I have a button that I want to highlight when the user clicks on it. I also want the other buttons to be not highlighted. In UIKit it would be simple to do this using sender.currentTitle.

Here is my code for the button

struct TipButton: View, Identifiable {
    var id: Int
    
    
    var tipPercentage: String
    @State var didTap: Bool = false
    @State var buttonLetter: String
    @State var zeroPctButton: Bool = false
    @State var tenPctButton: Bool = false
    @State var twentyPctButton: Bool = false

    
    var body: some View {
        Button {
            
            print("Tip is... \(Float(tipPercentage) ?? 7.7)")
            didTap.toggle()
            
            
            if buttonLetter == "A" {
                zeroPctButton = true
                tenPctButton = false
                twentyPctButton = false
                
            }
            else if buttonLetter == "B" {
                didTap = true
                
            }
            
            
        } label: {
            Text("\(tipPercentage)%")
                .font(.largeTitle)
                .bold()
        }
        .background(didTap ? Color.green : Color.clear)
    }
}

So far I've been playing around with it and adding different things like Identifiable and @State variables for the percentage amounts but can't figure this out.

In my main file I would have the view built along with these buttons like

struct ButtonsView: View {

var body: some View { 
    //blah blah 
    //some UI arranging code

    TipButton(id: 1, tipPercentage: "0", buttonLetter: "A")
    TipButton(id: 2, tipPercentage: "10", buttonLetter: "B")
    TipButton(id: 3, tipPercentage: "20", buttonLetter: "C")
}

}

As you can see, I've tried id and buttonLetter

In short, I want to click on button A, have it highlight, then when I click button B, it highlights and button A is no longer highlighted

1

There are 1 answers

0
jnpdx On BEST ANSWER

In order to do this, you'd want to move the @State from your child view into the parent view. Then, you can share it with the child view's through a Binding.

In this example, I have one @State variable that stores which id is highlighted. When a button is pressed, it simply updates the value.

struct TipButton: View, Identifiable {
    var id: Int
    var tipPercentage: String
    @Binding var highlightedID : Int
    
    var body: some View {
        Button {
            highlightedID = id
            print("Tip is... \(Float(tipPercentage) ?? 7.7)")
        } label: {
            Text("\(tipPercentage)%")
                .font(.largeTitle)
                .bold()
        }
        .background(id == highlightedID ? Color.green : Color.clear)
    }
}

struct ButtonsView: View {
    
    @State private var highlightedID : Int = 3
    
    var body: some View {
        TipButton(id: 1, tipPercentage: "0", highlightedID: $highlightedID)
        TipButton(id: 2, tipPercentage: "10", highlightedID: $highlightedID)
        TipButton(id: 3, tipPercentage: "20", highlightedID: $highlightedID)
    }
    
}