Taptic Engineを使ってみる
iOS 10からHaptic Feedbackという機能が追加されていたようです。
普段何気なくiPhone使っている上で当たり前になってしまっていますが、UIButtonをtapした時や、Picker Viewをぐるぐるした時などにデバイスがごくわずかに振動をしてフィードバックを行います。
UIFeedbackGenerator
UIFeedbackGeneratorはTaptic Engineを使う上での基底クラスで直接インスタンスを作ってしまうのは非推奨らしいです。
UINotificationFeecbackGenerator
UINotificationFeecbackGeneratorではFeedbackの種類が3種類存在し、成功、失敗、警告が用意されています。
prepare()で事前に呼び出しておくことで遅延を防ぎます。
private lazy var notificationFeedback: Any? = {
let generator: UIFeedbackGenerator = UINotificationFeedbackGenerator()
generator.prepare()
return generator
}()
イベントを発火させる部分でFeedbackのtypeを指定します。
if let generator = notificationFeedback as? UINotificationFeedbackGenerator {
//typeは.error, success, warningの3種類がある
generator.notificationOccurred(.warning)
}
UIImpactFeedbackGenerator
UINotificationFeecbackGeneratorとは違い宣言元でfeedbackの種類を決定します。UIImpactFeedbackGeneratorはUIButtonなどのfeedbackに使われており一番しっくりきました。
private lazy var impactFeedback: Any? = {
//styleは.light, .medium, heavyの3種類がある
let generator:UIFeedbackGenerator = UIImpactFeedbackGenerator(style: .medium)
generator.prepare()
return generator
}()
発火させる部分ではimpactOccurred()を呼び出します
if let generator = impactFeedback as? UIImpactFeedbackGenerator {
generator.impactOccurred()
}
UISelectionFeedbackGenerator
他の2つと比べFeedbackのタイプが1種類で固定されているためシンプルに実装できます。
UISelectionFeedbackGeneratorはPicker Viewをぐるぐる選択した際に使用されていると思われます。振動はだいぶ小さめです。
private lazy var selectionFeedback: Any? = {
let generator: UIFeedbackGenerator = UISelectionFeedbackGenerator()
generator.prepare()
return generator
}()
発火させる部分ではselectionChanged()を呼び出します
if let generator = selectionFeedback as? UISelectionFeedbackGenerator {
generator.selectionChanged()
}
コード
今回3種類のHaptic FeecbackをUIButtonのtapをトリガにして実装し、思ったことはHaptic Feedbackを感じされるタイミングはtouch dounの時がベストだということでした。
iosのボタンタップなどのタイミングはtouch upを基準に画面遷移やイベントの実行を行うことが多いですが、ボタンを長めに押している状態で指を話した時にFeedbackを感じると変な違和感を覚えました。
class ViewController: UIViewController {
private lazy var impactFeedback: Any? = {
//styleは.light, .medium, heavyの3種類がある
let generator:UIFeedbackGenerator = UIImpactFeedbackGenerator(style: .medium)
generator.prepare()
return generator
}()
private lazy var notificationFeedback: Any? = {
let generator: UIFeedbackGenerator = UINotificationFeedbackGenerator()
generator.prepare()
return generator
}()
private lazy var selectionFeedback: Any? = {
let generator: UIFeedbackGenerator = UISelectionFeedbackGenerator()
generator.prepare()
return generator
}()
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func notificationTaped(_ sender: Any) {
if let generator = notificationFeedback as? UINotificationFeedbackGenerator {
//typeは.error, success, warningの3種類がある
generator.notificationOccurred(.warning)
}
}
@IBAction func impactTaped(_ sender: Any) {
if let generator = impactFeedback as? UIImpactFeedbackGenerator {
generator.impactOccurred()
}
}
@IBAction func selectionTaped(_ sender: Any) {
if let generator = selectionFeedback as? UISelectionFeedbackGenerator {
generator.selectionChanged()
}
}
}