首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何在SwiftUI中为按钮创建触觉反馈?

如何在SwiftUI中为按钮创建触觉反馈?
EN

Stack Overflow用户
提问于 2019-06-25 15:06:15
回答 4查看 11.1K关注 0票数 22

在SwiftUI中,我正在尝试在点击按钮时实现触觉反馈。因此,我正在尝试使用simultaneousGesture,但我仍然在努力。我想不出水龙头什么时候开始响。

也没有为Swift UI实现触觉反馈,所以我猜我会从UIKit中混合它?

我试图实现TapGesture的更新方法,但它似乎什么也做不了。这就是我到目前为止所得到的。谢谢你的任何提示。

代码语言:javascript
复制
struct HapticButton : View {

    @GestureState var isDetectingTap = false

    var body: some View {

        let tap = TapGesture()
            .updating($isDetectingTap) { (body, stateType, transaction) in
                // nothing happens below
                print(body)
                print(stateType)
                print(transaction)
            }.onEnded { _ in
                // this one works but it is to late
                // I need to figure out the beginning of the tap
                print("Button was tapped, will invoke haptic feedback, maybe with UIKit")
        }

        return Button(action: {
            print("Action executed")
        }) {
            HStack {
                Image("icon")
                Text("Login")
            }
        }.simultaneousGesture(tap)
    }
}
EN

回答 4

Stack Overflow用户

发布于 2019-09-27 00:06:26

下面是纯SwiftUI解决方案:

代码语言:javascript
复制
HStack {
    Image("icon")
    Text("Login")
}
.onTouchGesture(
    touchBegan: { self.generateHapticFeedback = true },
    touchEnd: { _ in self.generateHapticFeedback = false }
)

只需将此代码片段添加到您的项目中的某个位置:

代码语言:javascript
复制
struct TouchGestureViewModifier: ViewModifier {
    let touchBegan: () -> Void
    let touchEnd: (Bool) -> Void

    @State private var hasBegun = false
    @State private var hasEnded = false

    private func isTooFar(_ translation: CGSize) -> Bool {
        let distance = sqrt(pow(translation.width, 2) + pow(translation.height, 2))
        return distance >= 20.0
    }

    func body(content: Content) -> some View {
        content.gesture(DragGesture(minimumDistance: 0)
                .onChanged { event in
                    guard !self.hasEnded else { return }

                    if self.hasBegun == false {
                        self.hasBegun = true
                        self.touchBegan()
                    } else if self.isTooFar(event.translation) {
                        self.hasEnded = true
                        self.touchEnd(false)
                    }
                }
                .onEnded { event in
                    if !self.hasEnded {
                        let success = !self.isTooFar(event.translation)
                        self.touchEnd(success)
                    }
                    self.hasBegun = false
                    self.hasEnded = false
                })
    }
}

extension View {
    func onTouchGesture(touchBegan: @escaping () -> Void = {},
                        touchEnd: @escaping (Bool) -> Void = { _ in }) -> some View {
        modifier(TouchGestureViewModifier(touchBegan: touchBegan, touchEnd: touchEnd))
    }
}
票数 3
EN

Stack Overflow用户

发布于 2019-06-27 07:31:59

您可以像这样使用UIFeedbackGenerator

代码语言:javascript
复制
let generator = UINotificationFeedbackGenerator()
generator.notificationOccurred(.error)

或者,当您使用SwiftUI时,您可以像这样使用CoreHaptics

代码语言:javascript
复制
let engine = try CHHapticEngine()
try engine.start()

let hapticEvent = CHHapticEvent(eventType: .hapticTransient, parameters: [
    CHHapticEventParameter(parameterID: .hapticSharpness, value: sharpness), CHHapticEventParameter(parameterID: .hapticIntensity, value: intensity),
], relativeTime: 0)
let audioEvent = CHHapticEvent(eventType: .audioContinuous, parameters: [
    CHHapticEventParameter(parameterID: .audioVolume, value: volume),
    CHHapticEventParameter(parameterID: .decayTime, value: decay),
    CHHapticEventParameter(parameterID: .sustained, value: 0),
], relativeTime: 0)

let pattern = try CHHapticPattern(events: [hapticEvent, audioEvent], parameters: [])
let hapticPlayer = try engine.makePlayer(with: pattern)
try hapticPlayer?.start(atTime: CHHapticTimeImmediate)
票数 1
EN

Stack Overflow用户

发布于 2021-06-23 02:00:18

您还可以将Haptic生成器封装在单例中:

代码语言:javascript
复制
import UIKit

class Haptics {
    static let shared = Haptics()
    
    private init() { }

    func play(_ feedbackStyle: UIImpactFeedbackGenerator.FeedbackStyle) {
        UIImpactFeedbackGenerator(style: feedbackStyle).impactOccurred()
    }
    
    func notify(_ feedbackType: UINotificationFeedbackGenerator.FeedbackType) {
        UINotificationFeedbackGenerator().notificationOccurred(feedbackType)
    }
}

调用站点:

代码语言:javascript
复制
// As a button action
Button(action: {
    // some action
    Haptics.shared.play(.heavy)
}, label: {
    Text("Button")
})

// As a tap gesture on a View
SomeView()
.onTapGesture(perform: {
    Haptics.shared.play(.light)
})

// In a function
func someFunc() {
    Haptics.shared.notify(.success)
}

选项:

代码语言:javascript
复制
Haptics.shared.play(.heavy)
Haptics.shared.play(.light)
Haptics.shared.play(.medium)
Haptics.shared.play(.rigid)
Haptics.shared.play(.soft)
                
Haptics.shared.notify(.error)
Haptics.shared.notify(.success)
Haptics.shared.notify(.warning)
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56748539

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档