如何在 swiftui 中按下按钮时更改按钮图像

Fre*_*Cox 7 image button swift

我想在按下按钮时更改图像名称。

到目前为止,这是我的结构:

struct ContentView: View { 
    @State var matrix = [Int] var 
    body: some View { 
        VStack { 
            Text("Test") 
            HStack(alignment: .center, spacing: 8) { 
                Button(action: { 
                    **
                    // call a func that will do some check and 
                    // change the image from Blue.png to Red.png
                    ** 
                }) { 
                    Image("Blue") 
                        .renderingMode(.original)
                        .resizable()                               
                        .aspectRatio(contentMode: .fill)
                        .clipShape(Circle()) 
                } 
            } 
        } 
    } 
 } 
Run Code Online (Sandbox Code Playgroud)

小智 7

我已经四处寻找一个好的解决方案,但它们都有其缺点。我经常看到的一种方法(此处)围绕创建一个具有识别用户触摸和释放的按钮内容的自ViewModifier定义DragGesture。该解决方案存在很多问题,主要是该手势优先于任何其他手势。这使得无法使用ScrollView.

从 iOS 13.0+ 开始,Apple 提供了一个ButtonStyle主要用于快速设置按钮样式的协议。该协议公开了一个isPressed完美反映按钮状态的变量。我的意思是,当您按住按钮并将手指拖动到其视图之外时,变量将从 变为true正如false您所期望的那样。我之前链接的解决方案并非如此。

问题的解决方案是首先定义一个带有变量绑定的新 ButtonStyle isPressed

struct IsPressedRegisterStyle : ButtonStyle {
    @Binding var isPressed : Bool
    func makeBody(configuration: Self.Configuration) -> some View {
        configuration.label
            .onChange(of: configuration.isPressed, perform: {newVal in
                isPressed = newVal
            })
    }
}
Run Code Online (Sandbox Code Playgroud)

然后使用以下样式:

struct IconButton : View {
    @State var width: CGFloat? = nil
    @State var height: CGFloat? = nil
    let action : () -> Void
    
    @State private var isPressed : Bool = false
    
    var body : some View {
        Image(isPressed ? "someImage" : "someOtherImage")
            .renderingMode(.original)
            .resizable()
            .scaledToFit()
            .frame(width: width, height: height)
            .overlay{
                GeometryReader{proxy in
                    Button(
                        action:{
                            action()
                        },
                        label: {
                            Spacer()
                                .frame(width: proxy.size.width, height: proxy.size.height)
                                .contentShape(Rectangle())
                        })
                        .buttonStyle(IsPressedRegisterStyle(isPressed: $isPressed))
                }
            }
    }
}
Run Code Online (Sandbox Code Playgroud)

ButtonStyle请注意其定义底部的自定义的使用。

快速浏览一下这里到底发生了什么:

  • 我们创建一个ImageButton使用间隔器覆盖跨越其整个区域的 a。
  • 按下图像会触发叠加按钮。
  • 我们应用的自定义将按钮的ButtonStyle内部变量公开给我们的视图。isPressedIconButton
  • 我们根据暴露值设置按钮图像。

您实例化一个按钮,如下所示:

// arbitrary values for width and height
IconButton(width: 200, height: 70){
    print("Button Pressed")
}
Run Code Online (Sandbox Code Playgroud)

我没有对这段代码进行过多的测试,所以请让我知道使用它是否有任何缺点。

干杯!