【iOS17】ハプティック・フィードバックで心地良い手触り感を演出する
はじめまして、株式会社TrashXでエンジニアをしているarmticです。iOS17からハプティック・フィードバック(触覚フィードバック)のAPIがSwiftUIに増えたので、実装方法について解説します。
概要
WWDC23のタイミングでiOS17が発表され、SwiftUIの世界でハプティック・フィードバックを返す方法が追加されました。
ViewModifier
として実装されていて、UIKitのAPI( UIFeedbackGenerator
系 )とは使い方が違うのでまとめました。
SwiftUIの世界からハプティック・フィードバックを呼び出すには、.sensoryFeedback
系を使用します。
nonisolated
func sensoryFeedback<T>(
_ feedback: SensoryFeedback,
trigger: T
) -> some View where T : Equatable
第一引数にはハプティックの種類を決めるSensoryFeedback
を渡し、trigger
にはEquatable
を渡します。triggerの値に変化があるとハプティックが作動します。
最小構成での実装例
ボタンを押すとcount
がインクリメントされ、.selection
フィードバックが返ってきます。
@State var count = 0
var body: some View {
Button {
count += 1
} label: {
Text("Increment")
}
.sensoryFeedback(.selection, trigger: count)
}
ハプティックのオンオフ / 種類の出し分け
- 「アプリがフォアグラウンド状態に戻ってきた時にフィードバックを返したい」
- 「条件に応じてフィードバックの種類を出し分けたい」
といったケースのために用意されたAPIも存在します。
条件がtrueの時にフィードバックを返すには
前者の「アプリがフォアグラウンド状態に戻ってきた時にフィードバックを返したい」のように、条件がtrueの時にフィードバックを返したい場合はこのAPIを利用します。
nonisolated
func sensoryFeedback<T>(
_ feedback: SensoryFeedback,
trigger: T,
condition: @escaping (T, T) -> Bool
) -> some View where T : Equatable
実装例
@Environment(\.scenePhase) var scenePhase: ScenePhase
var body: some View {
Text("Hello")
.sensoryFeedback(.selection, trigger: scenePhase) { _, newValue in
newValue == .active
}
}
ScenePhase
にはシーンの状態が入ります。.active
, .inactive
, .background
の3つの値を取る列挙型になっています。
条件に応じてフィードバックの種類を出し分けるには
あらかじめSensoryFeedbackを指定せず、動的にフィードバックの種類を出し分けることもできます。
trigger
に指定した値が変化すると、feedback
クロージャで返ってきたフィードバックを再生するAPIです。
nonisolated
func sensoryFeedback<T>(
trigger: T,
_ feedback: @escaping (T, T) -> SensoryFeedback?
) -> some View where T : Equatable
実装例
TextField
で名前を入力し、30文字以下というバリデーションを設けるケースを考えます。
name
の値が変更されるとfeedback
のクロージャが呼び出され、name.count
に応じて返すフィードバックを出し分け流ことができます。
今回は30文字以上を受け付けないので、それ以上入力しようとすると.error
のフィードバックを返すようにします。
@State var name = ""
var body: some View {
TextField("your name", text: $name)
.sensoryFeedback(trigger: name) { _, newValue in
switch newValue.count {
case 30...:
// 30文字以上は受け付けないことを`error`で表現
return .error
case 25...:
// もう直ぐ入力上限に達することを`warning`で表現
return .warning
default:
// フィードバックを返さない
return nil
}
}
}
SensoryFeedbackの種類
sensoryFeedback
に指定できる種類はドキュメントに記載があります。振動の強さや鋭さが違うハプティックを効果的に使うことで印象が変わります。
Human Interface GuidelinesのPlaying Hapticsにも記載がある通り、ハプティックの意味と使い所を理解し、アプリ全体で一貫したハプティックを使うことが重要になります。
XcodeでSensoryFeedback
の定義にジャンプして確認することもできます。
Core Hapticsでさらに複雑なハプティックを設計する
Core Haptics
フレームワークの世界に飛び込んで、さらに複雑なハプティックを設計することも可能です。弊社がつくっているNow Cameraでは、使い心地を追求するために独自のAHAP
ファイルを定義してハプティックを設計しています。
事例
いざハプティックを使おう!となった際、実装者によってHIGの解釈がまちまちだと一貫したルールがなく、効果が薄れるかもしれません。チームやプロジェクト内で使い所や意義を共有できていると運用が楽になります。
ハプティックのルールを策定し、運用する方法についての13anさんの記事を紹介します。
関連
Discussion