'Add border to only 1 button
I have a simple setup where I have 2 buttons and when a user clicks on one of them I want a border to show around it so that they know which one they clicked
I only ever want 1 button to have a border at once
I came up with this
import SwiftUI
struct TestView: View {
@State var isBorder:Bool = false
var body: some View {
VStack{
Button {
isBorder.toggle()
} label: {
Label("Sports", systemImage: "sportscourt")
}
.foregroundColor(.black)
.padding()
.background(Color(hex: "00bbf9"))
.cornerRadius(8)
.overlay(isBorder ? RoundedRectangle(cornerRadius: 8).stroke(Color.black, lineWidth:2) : nil)
Button {
isBorder.toggle()
} label: {
Label("Firends", systemImage: "person")
}
.foregroundColor(.black)
.padding()
.background(Color(hex: "fee440"))
.cornerRadius(8)
.overlay(isBorder ? RoundedRectangle(cornerRadius: 8).stroke(Color.black, lineWidth:2) : nil)
}
}
}
struct TestView_Previews: PreviewProvider {
static var previews: some View {
TestView()
}
}
But a border shows around both buttons because I am using 1 variable "isBorder"
How could I adapt my solution so that I can accommodate for more buttons
Solution 1:[1]
As the comments allready stated this should be encapsulated in its own view. But here you also have the additional problem with the shared state of what button is clicked.
First create an enum that holds all properties a button has that distinguishes it from others:
enum ButtonEnum: Int, CaseIterable{
case sports, friends
var systemIcon: String{
switch self{
case .sports:
return "sportscourt"
case .friends:
return "person"
}
}
var label: String{
switch self{
case .sports:
return "Sports"
case .friends:
return "Friends"
}
}
var backgroundColor: Color{
switch self{
case .sports:
return Color("00bbf9")
case .friends:
return Color("fee440")
}
}
}
Then create a View that represents that button:
struct BorderedButton: View{
@Binding var selected: ButtonEnum?
var buttonType: ButtonEnum
var action: () -> Void
var body: some View{
Button {
selected = buttonType
action()
} label: {
Label(buttonType.label, systemImage: buttonType.systemIcon)
}
.foregroundColor(.black)
.padding()
.background(buttonType.backgroundColor)
.cornerRadius(8)
.overlay(selected == buttonType ? RoundedRectangle(cornerRadius: 8).stroke(Color.black, lineWidth:2) : nil)
}
}
and usage example:
struct TestView: View {
@State private var selected: ButtonEnum? = nil
var body: some View {
VStack{
BorderedButton(selected: $selected, buttonType: .friends) {
print("friends pressed")
}
BorderedButton(selected: $selected, buttonType: .sports) {
print("sports selected")
}
}
}
}
This solution can be easily expanded by adding new cases to the enum.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | burnsi |