如何创建一个 SwiftUI 按钮来更改不透明度并在触摸时触发按钮操作?

Smo*_*p69 5 swiftui

我想用 SwiftUI 创建一个按钮,当我的手指触摸它时就会触发它(就像 UIKit 的触摸而不是触摸内部)。我还希望当我的手指按下按钮时按钮的不透明度变为 0.7。我希望只有当我的手指不再触摸按钮时,按钮的不透明度才变回 1。

我尝试了两种不同类型的按钮样式来创建这样的按钮,但都失败了:

    struct ContentView: View {  
        var body: some View {  
            Button(action: {  
                print("action triggered")  
            }){  
                Text("Button").padding()  
            }  
                .buttonStyle(SomeButtonStyle())  
        }  
    }  

    struct SomeButtonStyle: ButtonStyle {  
        func makeBody(configuration: Self.Configuration) -> some View {  
            configuration.label  
                .background(Color.green)  
                .opacity(configuration.isPressed ? 0.7 : 1)  
                .onLongPressGesture(  
                    minimumDuration: 0,  
                    perform: configuration.trigger//Value of type 'SomeButtonStyle.Configuration' (aka 'ButtonStyleConfiguration') has no member 'trigger'  
                )  
        }  
    }  

    struct SomePrimativeButtonStyle: PrimitiveButtonStyle {  
        func makeBody(configuration: Configuration) -> some View {  
          configuration.label  
            .background(Color.green)  
            .opacity(configuration.isPressed ? 0.7 : 1)//Value of type 'SomePrimativeButtonStyle.Configuration' (aka 'PrimitiveButtonStyleConfiguration') has no member 'isPressed'  
            .onLongPressGesture(  
              minimumDuration: 0,  
              perform: configuration.trigger  
            )  
        }  
    }
Run Code Online (Sandbox Code Playgroud)

显然,上面的按钮样式都不起作用,因为 ButtonStyle 和 PrimitiveButtonStyle 不共享相同的方法和属性,因此我不能在同一个中同时使用 isPressed 属性(属于 ButtonStyle)和触发方法(属于 PrimitiveButtonStyle)按钮样式。

我应该如何配置按钮样式才能实现此功能?

Але*_*кий 4

好的,我知道作者只想看到解决方案Button,所以我进一步挖掘。并在Swift UI Lab发现了一些有趣的东西。这个想法与我的第一个答案相同:使用@GestureState并创建LongPressGesture这个.updating($...)状态。但PrimitiveButtonStyle你不需要将几个手势组合在一起。因此,我稍微简化了代码并在模拟器上进行了测试。我认为现在这正是作者所需要的:

struct ComposingGestures: View {

    var body: some View {

        Button(action: {
            print("action triggered")
        }){
            Text("Button")
                .padding()
        }
            .buttonStyle(MyPrimitiveButtonStyle())

    }

}

struct MyPrimitiveButtonStyle: PrimitiveButtonStyle {

    func makeBody(configuration: PrimitiveButtonStyle.Configuration) -> some View {
        MyButton(configuration: configuration)
    }

    struct MyButton: View {
        @GestureState private var pressed = false

        let configuration: PrimitiveButtonStyle.Configuration
        let color: Color = .green

        @State private var didTriggered = false

        var body: some View {
            // you can set minimumDuration to Double.greatestFiniteMagnitude if you think that
            // user can hold button for such a long time
            let longPress = LongPressGesture(minimumDuration: 300, maximumDistance: 300.0)
                .updating($pressed) { value, state, _ in
                    state = value
                    self.configuration.trigger()
            }

            return configuration.label
                .background(Color.green)
                .opacity(pressed ? 0.5 : 1.0)
                .gesture(longPress)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)