首页 > 解决方案 > 如何让这些 SwiftUI 文本“按钮”在点击时改变颜色?

问题描述

在 SwiftUI 中,如何让这些文本“按钮”在点击时更改颜色,但在您移开手指时恢复?

https://i.imgur.com/WHPGhAT.jpg

按钮代码如下所示:

    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
                }
            }
    }

标签: iosswiftmobileswiftui

解决方案


您可以使用自定义ButtonStyle来执行此操作:

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
    }
}

请注意,您的Text视图现在被包裹在 a 中Button并被赋予了 buttonStyle CustomButtonStyle

在里面CustomButtonStyle,我使用了一个三元表达式来设置背景的RoundedRectangle颜色configuration.isPressed

我还展示了如何传入另一个参数 ( isSelected),因为在您的原始示例中,您可能也希望基于此有条件地执行操作。


更新显示列的完整工作示例:
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
    }
}

推荐阅读