iOS——關于-Taptic-Engine-震動反饋
上周,leader 拿著 iPhone 7 打開了網易新聞,問我:『你看,你這里的下拉刷新是 短震動 ,我們的手機數周遙控電視的時候只有 長震動 ,產品那邊問能不能用短震動』。
然后博主就去查看了一下關于短震動的方式,整個過程可以描述為——『資料真少!』。
不過最后通過一下午的搜集,最終還是總結整理出來了這份文檔,也補充了自己對 iPhone 6s 之后對 Taptic Engine 的了解。
Taptic Engine
先了解一個概念——Taptic Engine
Taptic Engine 是蘋果產品上推出的全新震動模塊,該元件最早出現在 Apple Watch 中。iPhone 6s 和 iPhone 6s Plus 中,也同樣內置了Taptic Engine,在設計上有所升級。
Taptic Engine 振動模塊為 Apple Watch 以及 iPhone 6s、iPhone 7 提供了 Force Touch 以及 3D Touch,不同的屏幕操作,可以感受到不同的振動觸覺效果,帶來更好的用戶體驗。
短震方法一 AudioServicesPlaySystemSound
常用調用:
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
以上代碼在各個型號手機中反應為長震
API 系統版本支持:
__OSX_AVAILABLE_STARTING(__MAC_10_5,__IPHONE_2_0);
APPLE 公開的 SystemSoundID 有:
CF_ENUM(SystemSoundID)
{
kSystemSoundID_UserPreferredAlert = 0x00001000,
kSystemSoundID_FlashScreen = 0x00000FFE,
// this has been renamed to be consistent
kUserPreferredAlert = kSystemSoundID_UserPreferredAlert
};
CF_ENUM(SystemSoundID)
{
kSystemSoundID_Vibrate = 0x00000FFF
};
以上類型 沒有短震動 。
但通過以下代碼,可以得到更多類型的震動:
// 普通短震,3D Touch 中 Peek 震動反饋
AudioServicesPlaySystemSound(1519);
// 普通短震,3D Touch 中 Pop 震動反饋
AudioServicesPlaySystemSound(1520);
// 連續三次短震
AudioServicesPlaySystemSound(1521);
但以上 ID 均未在 Apple 的 Documents 中描述。顯然, 這是調用了一些私有一些屬性 。
短震方法二 獲取 _tapticEngine
id tapticEngine = [[UIDevice currentDevice] performSelector: NSSelectorFromString(@"_tapticEngine")
withObject:nil];
[tapticEngine performSelector: NSSelectorFromString(@"actuateFeedback:")
withObject:@(0)];
或者:
id tapticEngine = [[UIDevice currentDevice] performSelector: NSSelectorFromString(@"_tapticEngine")
withObject:nil];
SEL selector = NSSelectorFromString(@"actuateFeedback:");
int32_t arg = 1001;
NSInvocation *inv = [NSInvocation invocationWithMethodSignature:[tapticEngine methodSignatureForSelector:selector]];
[inv setTarget:tapticEngine];
[inv setSelector:selector];
[inv setArgument:&arg atIndex:2];
[inv invoke];
顯然, 這是調用了私有 API 。
這些方法,在實際測試的時候發現,在 iPhone 7 上調用沒有震動反饋,在 iPhone 6S Plus 上調用有震動反饋,在 iPhone 6 上調用 無反饋。
短震方法三 UIImpactFeedbackGenerator
iOS10 引入了一種新的、產生觸覺反饋的方式, 幫助用戶認識到不同的震動反饋有不同的含義 。這個功能的核心就是由 UIFeedbackGenerator 提供。
UIFeedbackGenerator 可以幫助你實現 haptic feedback。它的要求是:
- 支持 Taptic Engine 機型 (iPhone 7 以及 iPhone 7 Plus).
- app 需要在前臺運行
- 系統 Haptics setting 需要開啟
Apple 曾表示公開了 Taptic Engine 的 API,但是鮮有文檔。在搜羅了各種資料后,可以認為 UIImpactFeedbackGenerator 即 Taptic Engine 的 公開 API。
它的調用方式是:
UIImpactFeedbackGenerator *generator = [[UIImpactFeedbackGenerator alloc] initWithStyle: UIImpactFeedbackStyleLight];
[generator prepare];
[generator impactOccurred];
Others
觀察 UIImpactFeedbackGenerator 你會發現它繼承于 UIFeedbackGenerator 。除了 UIImpactFeedbackGenerator 還有三種 FeedbackGenerator:
- UIImpactFeedbackGenerator
- UISelectionFeedbackGenerator
- UINotificationFeedbackGenerator
對于震動反饋的應用,Apple 也給出了示例場景:
- (IBAction)gestureHandler:(UIPanGestureRecognizer *)sender {
switch (sender.state) {
case UIGestureRecognizerStateBegan:
// Instantiate a new generator.
self.feedbackGenerator = [[UISelectionFeedbackGenerator alloc] init];
// Prepare the generator when the gesture begins.
[self.feedbackGenerator prepare];
break;
case UIGestureRecognizerStateChanged:
// Check to see if the selection has changed...
if ([self myCustomHasSelectionChangedMethodWithTranslation:[sender translationInView: self.view]]) {
// Trigger selection feedback.
[self.feedbackGenerator selectionChanged];
// Keep the generator in a prepared state.
[self.feedbackGenerator prepare];
}
break;
case UIGestureRecognizerStateCancelled:
case UIGestureRecognizerStateEnded:
case UIGestureRecognizerStateFailed:
// Release the current generator.
self.feedbackGenerator = nil;
break;
default:
// Do nothing.
break;
}
}
三種方法在測試機上不同的反饋結果
AudioServicesPlaySystemSound | 1519 | 1520 | 1521 |
---|---|---|---|
iPhone 7(iOS 10) | peek 觸感 | pop 觸感 | 三次連續短振 |
iPhone 6s Puls(iOS 9) | peek 觸感 | pop 觸感 | 三次連續短振 |
iPhone 6(iOS 10) | 無振動 | 無振動 | 無振動 |
獲取 _tapticEngine | |
---|---|
iPhone 7(iOS 10) | 無振動 |
iPhone 6s Puls(iOS 9) | 長振 |
iPhone 6(iOS 10) | 無振動 |
UIImpactFeedbackGenerator | .Light | .Medium | .Heavy |
---|---|---|---|
iPhone 7(iOS 10) | 微弱短振 | 中等短振 | 明顯短振 |
iPhone 6s Puls(iOS 9) | 長振 | 長振 | 長振 |
iPhone 6(iOS 10) | 無振動 | 無振動 | 無振動 |
總結一下,希望同樣的代碼能在更多的機型上實現短振,建議使用 AudioServicesPlaySystemSound(1519)。不過可能會涉及到調用私有 API。安全起見,可以使用 UIImpactFeedbackGenerator 。
來自:http://zhoulingyu.com/2017/01/16/iOS——關于-Taptic-Engine-震動反饋/