主要内容翻译自:SwiftUI Sensory Feedback

iOS 17 中,SwiftUI 增加了一个地道的 modifier 来供给轰动反应。

SwiftUI 经典状况再现。好消息:咱们新增了一个 modifier 实现了 UIKit 的一个功能,更加优雅。坏消息:从最新的版别的 iOS 开始支持。

在 iOS 17 之前的状况

在 iOS 17 之前,轰动反应经过 UIFeedbackGenerator的子类实现(UIImpactFeedbackGenerator、UISelectionFeedbackGenerator. UINotificationFeedbackGenerator )。

运用的方法大概这样:

struct OldFeedback: View {
    @State var value: Bool = true
    let generator = UISelectionFeedbackGenerator()
    var body: some View {
        Toggle("Switch", isOn: $value)
            .onChange(of: value, {
                generator.selectionChanged()
            })
    }
}

iOS 17:Sensory Feedback

在 iOS 17 中引入了原生的 sensoryFeedback modifier:

struct Feedback: View {
    @State var value: Bool = true
    var body: some View {
        Toggle("Switch", isOn: $value)
            .sensoryFeedback(.selection, trigger: value)
    }
}

这个方法还很贴心的添加了尾随的判断闭包,相似 filter。因为咱们或许不是每次值的改换都轰动,能够把筛选条件加到闭包里:

struct Feedback: View {
    @State var value: Bool = true
    var body: some View {
        Toggle("Switch", isOn: $value)
            .sensoryFeedback(.selection, trigger: value,
                             condition: { oldValue, newValue in
                if newValue == true {
                    return true
                } else {
                    return false
                }
            })
    }
}

还有一个签名是能够经过调查的值来回来不同的轰动:

struct Feedback: View {
    @State var value: Bool = true
    var body: some View {
        Toggle("Switch", isOn: $value)
            .sensoryFeedback(trigger: value) { oldValue, newValue in
                if newValue == true {
                    return SensoryFeedback.selection
                } else {
                    return SensoryFeedback.warning
                }
            }
    }
}

不同的渠道的差异

SwiftUI 天生就支持苹果全渠道。轰动反应又具有渠道特性(比方在 mac 上便是触摸板的轰动,在手表上是 taptic engine),因而轰动选项 SensoryFeedback 的值也是区别渠道的。小常识:iPad 上没有轰动。

watchOS only

  • start: Activity started
  • stop: Activity stopped

start 和 stop 通常用来表明一个活动的开始和结束(比方手表上的计时)。

macOS only

  • alignment: a dragged item is in alignment with another item.
  • levelChange: indicates movement between discrete levels of pressure. For example, holding a fast-forward button.

这两个轰动都是针对 mac 的触摸板的。alignment 场景是当你拖动一个元素时,要提醒对齐状态时给与的小轰动。levelChange 场景是按压的力度,比方长按一个元素能够敞开排序,能够给出一个相似于重按的反应。

watchOS & iOS

剩余的选项都是 watchOS 和 iOS 通用的。

轰动选项有这些:

  • decrease: Important value decreased below a significant threshold
  • increase: Important value increased above a significant threshold

特别要提一下的是 decrease、increase。这两种轰动文档上写的是 watchOS only,但是现在在 iOS 也能够正常轰动。

  • selection: A UI element’s values are changing.
  • success: A task completed successfully
  • warning: A task produced a warning
  • error: A task produced an error
  • impact: A physical impact when UI elements collide.

自界说轰动参数

impact 这个选项中,还额外给了两个参数来调理轰动:

  • weight:调理轰动的强度,有light、medium、heavy三档。你乃至能够在这个基础上再设置强度,他真的我哭死。
  • flexibility:震感曲线,能够理解为绷簧的软硬,轰动是洪亮仍是柔软一点,有rigid、solid、soft三档。你乃至能够在这个基础上再设置强度,他真的我哭死。

代码演示:

struct Feedback: View {
    @State var value: Bool = true
    var body: some View {
        Toggle("Switch", isOn: $value)
            .sensoryFeedback(trigger: value) { oldValue, newValue in
                if newValue == true {
                    return SensoryFeedback.impact(weight: .light, intensity: 1.5)
                } else {
                    return SensoryFeedback.impact(flexibility: .rigid, intensity: 2.0)
                }
            }
    }
}

HIG 运用主张

苹果在 HIG 中对怎么(Human Interface Guidelines – Playing haptics)运用轰动有说到一些主张:

  • 轰动的类型和体系界说一致。比方体系供给了选中的轰动,用户在体系其他地方也很熟悉选中的轰动,这个时分 app 里就主张运用和体系行为一致的轰动方法。
  • 不用过度运用。
  • 能够允许用户封闭轰动。
  • 整个 app 中的轰动逻辑要保持一致。