SwiftUI:触控反馈

时间:2022-07-26
本文章向大家介绍SwiftUI:触控反馈,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

尽管 SwiftUI 并未内置任何触控反馈功能,但对于我们来说,使用 UIKit 和 Core Haptics 进行添加非常容易,这是两个内置于系统中的框架,并且可在所有现代 iPhone 上使用。如果您以前从未听说过“触控反馈”,则“触控反馈”涉及设备中的小型电动机,从而产生诸如敲击和振动之类的感觉。

UIKit 的触控反馈实现非常简单,但这并不意味着您应该排除它:它很简单,因为它专注于内置触控反馈,例如“成功”或“失败”,这意味着用户可以学习感觉如何也就是说,如果您使用成功触控反馈,那么某些用户——尤其是那些更依赖触觉的用户,例如盲人用户——将能够知道操作的结果而无需从您的应用程序获得任何进一步的输出。

要尝试 UIKit 的触控反馈,请将此方法添加到 ContentView 中:

func simpleSuccess() {
    let generator = UINotificationFeedbackGenerator()
    generator.notificationOccurred(.success)
}

您可以使用一个简单的onTapGesture()触发它,例如:

Text("Hello, World!")
    .onTapGesture(perform: simpleSuccess)

尝试将.success替换为.error.warning,看看是否可以分辨出其中的区别——我认为,.success.warning相似但不同。

对于更高级的触控反馈,Apple 为我们提供了一个名为 Core Haptics 的整体框架。这东西感觉像是背后的Apple团队的真爱之作,而且我认为它是 iOS 13 中真正的隐藏宝石之一——在看到其说明后我便立即扑向了它!

核心触觉使我们可以通过组合拍子,连续振动,参数曲线等来创建可大规模定制的触觉。我不想在这里过分深入,因为这有点题外话,但我至少想举一个例子,让您自己尝试一下。

首先,在 ContentView.swift 顶部附近添加此新导入:

import CoreHaptics

接下来,我们需要创建一个CHHapticEngine实例作为属性——这是负责产生振动的实际对象,因此我们需要在需要实现触控反馈效果之前先创建它。

@State private var engine: CHHapticEngine?

我们将在主视图出现后立即创建它。创建引擎时,您可以附加处理程序以帮助停止活动时恢复活动,例如当应用程序移至后台时,但是在这里,我们将使其保持简单:如果当前设备支持触控反馈,我们将启动引擎,如果失败,则打印错误。

将此方法添加到ContentView

func prepareHaptics() {
    guard CHHapticEngine.capabilitiesForHardware().supportsHaptics else { return }

    do {
        self.engine = try CHHapticEngine()
        try engine?.start()
    } catch {
        print("There was an error creating the engine: (error.localizedDescription)")
    }
}

现在,有趣的部分是:我们可以配置参数来控制触觉的强度(.hapticIntensity)和“锐度”的强度(.hapticSharpness),然后将它们放入具有相对时间偏移的触觉事件中。“锐度”是一个奇怪的术语,但是一旦您尝试过,它就会更有意义——锐度值为0相比于值1确实确实很钝。至于相对时间,这使我们可以创建很多单个序列中的触觉事件。

立即将此方法添加到ContentView

func complexSuccess() {
    // 确保设备支持触控反馈
    guard CHHapticEngine.capabilitiesForHardware().supportsHaptics else { return }
    var events = [CHHapticEvent]()

    // 创建一个强烈而尖锐的拍子
    let intensity = CHHapticEventParameter(parameterID: .hapticIntensity, value: 1)
    let sharpness = CHHapticEventParameter(parameterID: .hapticSharpness, value: 1)
    let event = CHHapticEvent(eventType: .hapticTransient, parameters: [intensity, sharpness], relativeTime: 0)
    events.append(event)

    // 将这些事件转换为模式并立即播放
    do {
        let pattern = try CHHapticPattern(events: events, parameters: [])
        let player = try engine?.makePlayer(with: pattern)
        try player?.start(atTime: 0)
    } catch {
        print("Failed to play pattern: (error.localizedDescription).")
    }
}

要试用我们的自定义触控反馈,请将ContentViewbody属性修改为此:

Text("Hello, World!")
    .onAppear(perform: prepareHaptics)
    .onTapGesture(perform: complexSuccess)

这样可以确保触控系统已启动,从而使点击手势正常工作。

如果要进一步尝试触觉,请使用所需的任何触觉替换 let intensity, let sharpness, 和 let event。例如,如果用下面的代码替换这三行,则将获得几次点击,然后依次增加强度和清晰度:

for i in stride(from: 0, to: 1, by: 0.1) {
    let intensity = CHHapticEventParameter(parameterID: .hapticIntensity, value: Float(i))
    let sharpness = CHHapticEventParameter(parameterID: .hapticSharpness, value: Float(i))
    let event = CHHapticEvent(eventType: .hapticTransient, parameters: [intensity, sharpness], relativeTime: i)
    events.append(event)
}

for i in stride(from: 0, to: 1, by: 0.1) {
    let intensity = CHHapticEventParameter(parameterID: .hapticIntensity, value: Float(1 - i))
    let sharpness = CHHapticEventParameter(parameterID: .hapticSharpness, value: Float(1 - i))
    let event = CHHapticEvent(eventType: .hapticTransient, parameters: [intensity, sharpness], relativeTime: 1 + i)
    events.append(event)
}

译自 Making vibrations with UINotificationFeedbackGenerator and Core Haptics