In SwiftUI, how can I make these text "buttons" change color on tap, but revert when you remove your finger?
https://i.sstatic.net/1R0OJ.jpg
Here's what the button code looks like:
LazyVGrid(columns:
Array(repeating:
GridItem(.flexible(),
spacing: 5),
count: 2),
spacing: 2) {
ForEach(viewModel.productIngredients, id: \.self) { ingredient in
Text(ingredient.name)
.font(.system(size: 14))
.fontWeight(.medium)
.foregroundColor(.black)
.padding(8)
.background(RoundedRectangle(cornerRadius: 10).stroke(Color.black, lineWidth: 2))
.padding(.top,5)
/// .background(self.selectedIngredient == ingredient ? Color.blue : Color.white)
.onTapGesture {
self.didTap.toggle()
self.selectedIngredient = ingredient
}
}
}
You can use a custom ButtonStyle
to do this:
struct ContentView : View {
var body: some View {
Button(action: {
//Your action code, taken from the previous `onTapGesture` in the original code
//didTap.toggle()
//selectedIngredient = ingredient
}) {
Text("Ingredient")
.fontWeight(.medium)
}.buttonStyle(CustomButtonStyle(isSelected: false)) //could pass a parameter here like isSelected: selectedIngredient == ingredient from your original code
}
}
struct CustomButtonStyle : ButtonStyle {
var isSelected: Bool
func makeBody(configuration: Configuration) -> some View {
configuration.label
.font(.system(size: 14))
.foregroundColor(.black)
.padding(8)
.background(RoundedRectangle(cornerRadius: 10)
.stroke(configuration.isPressed ? Color.red : Color.black, lineWidth: 2)
)
.padding(.top,5)
//Could also modify style based on isSelected
}
}
Notice that your Text
view is now wrapped in a Button
and given a buttonStyle of CustomButtonStyle
.
Inside CustomButtonStyle
, I use a ternary expression to set the color of the background RoundedRectangle
based on configuration.isPressed
.
I also showed how you could pass in another parameter (isSelected
) because in your original example it looked like you may want to do things conditionally based on that as well.
struct Ingredient : Identifiable, Hashable {
var id = UUID()
var name = "Ingredient"
}
struct ContentView: View {
@State var ingredients = [Ingredient(),Ingredient(),Ingredient(),Ingredient(),Ingredient(),Ingredient(),Ingredient(),Ingredient()]
var body: some View {
LazyVGrid(columns:
Array(repeating:
GridItem(.flexible(),
spacing: 5),
count: 2),
spacing: 2) {
ForEach(ingredients, id: \.self) { ingredient in
Button(action: {
//Your action code, taken from the previous `onTapGesture` in the original code
//didTap.toggle()
//selectedIngredient = ingredient
}) {
Text(ingredient.name)
.fontWeight(.medium)
}.buttonStyle(CustomButtonStyle(isSelected: false))
}
}
}
}
struct CustomButtonStyle : ButtonStyle {
var isSelected: Bool
func makeBody(configuration: Configuration) -> some View {
configuration.label
.font(.system(size: 14))
.foregroundColor(.black)
.padding(8)
.background(RoundedRectangle(cornerRadius: 10)
.stroke(configuration.isPressed ? Color.red : Color.black, lineWidth: 2)
)
.padding(.top,5)
//Could also modify style based on isSelected
}
}