【问题标题】:Detect "On Tap End" on Button检测按钮上的“On Tap End”
【发布时间】:2021-02-23 17:15:51
【问题描述】:

我正在开发一个简单的 MIDI 键盘。每个钢琴键都是一个按钮。只要你按下它,它就会向虚拟设备发送一个“MIDI note ON”信号:

Button(action: {
    MidiDevice.playNote("C")
}) { 
    Image(systemName: "piano-white-key")
}

它工作正常。延迟很好,用户可以在几分之一秒内弹奏按键,或者按住按钮以获得更长的音符。现在,如何拦截“用户抬起手指”的动作以便立即发送MidiDevice.stopNote("C") 事件?

【问题讨论】:

标签: swiftui


【解决方案1】:

这是可能的解决方案(据我了解您的目标) - 使用 ButtonStyle 检测 isPressed 状态。标准Button 发送点击 UP 的动作,所以我们只需添加点击 DOWN 的动作处理程序。

使用 Xcode 12.4 / iOS 14.4 测试

struct ButtonPressHandler: ButtonStyle {
    var action: () -> ()
    func makeBody(configuration: Self.Configuration) -> some View {
        configuration.label
            .foregroundColor(configuration.isPressed ? 
                  Color.blue.opacity(0.7) : Color.blue)   // just to look like system
            .onChange(of: configuration.isPressed) {
                if $0 {
                    action()
                }
            }
    }
}

struct TestButtonPress: View {
    var body: some View {
        Button(action: {
            print(">> tap up")
        }) {
            Image(systemName: "piano-white-key")
        }
        .buttonStyle(ButtonPressHandler {
            print("<< tap down")
        })
    }
}

【讨论】:

  • 这很漂亮
  • 我希望 SwiftUI 能够在本地处理这个问题,但这是完美的,谢谢。
【解决方案2】:

除了 Asperi 的 answer,您还可以创建一个扩展,使其更具SwiftUI 风格

extension Button {
    func onTapEnded(_ action: @escaping () -> Void) -> some View {
        buttonStyle(ButtonPressHandler(action: action))
    }
}
struct ContentView: View {
    var body: some View {
        Button(action: {
            print(">> tap up")
        }) {
            Image(systemName: "piano-white-key")
        }
        .onTapEnded {
            print("<< tap down")
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-11-03
    • 2017-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-30
    相关资源
    最近更新 更多