关于Taptic Engine震动反馈

What has Happened?

上周,leader 拿着 iPhone 7 打开了网易新闻,问我:『你看,你这里的下拉刷新是短震动,我们的手机数周遥控电视的时候只有长震动,产品那边问能不能用短震动』。

然后博主就去查看了一下关于短震动的方式,整个过程可以描述为——『资料真少!』。

不过最后通过一下午的搜集,最终还是总结整理出来了这份文档,也补充了自己对 iPhone 6s 之后对 Taptic Engine 的了解。

关于 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

常用调用:

 
  
  1. AudioServicesPlaySystemSound(kSystemSoundID_Vibrate); 

以上代码在各个型号手机中反应为长震

API 系统版本支持:

 
  
  1. __OSX_AVAILABLE_STARTING(__MAC_10_5,__IPHONE_2_0); 

APPLE 公开的 SystemSoundID 有:

 
  
  1. CF_ENUM(SystemSoundID) 
  2. kSystemSoundID_UserPreferredAlert = 0x00001000, 
  3. kSystemSoundID_FlashScreen = 0x00000FFE, 
  4. // this has been renamed to be consistent 
  5. kUserPreferredAlert = kSystemSoundID_UserPreferredAlert 
  6. }; 
  7.   
  8. CF_ENUM(SystemSoundID) 
  9. kSystemSoundID_Vibrate = 0x00000FFF 
  10. };  

以上类型 没有短震动 。

但通过以下代码,可以得到更多类型的震动:

 
  
  1. // 普通短震,3D Touch 中 Pop 震动反馈 
  2. AudioServicesPlaySystemSound(1520);  
 
  
  1. // 普通短震,3D Touch 中 Peek 震动反馈 
  2. AudioServicesPlaySystemSound(1519);  
 
  
  1. // 连续三次短震 
  2. AudioServicesPlaySystemSound(1521);  

但以上 ID 均未在 Apple 的 Documents 中描述。显然,这是调用了一些私有一些属性 。

关于是否调用了私有 API,也有一些讨论,可以查看这里(https://forums.developer.apple.com/thread/45628)。

短震方法二 获取 _tapticEngine

这种方法是从这里(https://unifiedsense.com/development/using-taptic-engine-on-ios.html)搜集到的。

 
  
  1. id tapticEngine = [[UIDevice currentDevice] performSelector: NSSelectorFromString(@"_tapticEngine"
  2. withObject:nil]; 
  3. [tapticEngine performSelector: NSSelectorFromString(@"actuateFeedback:"
  4. withObject:@(0)];  

或者:

 
  
  1. id tapticEngine = [[UIDevice currentDevice] performSelector: NSSelectorFromString(@"_tapticEngine"
  2. withObject:nil]; 
  3.   
  4. SEL selector = NSSelectorFromString(@"actuateFeedback:"); 
  5. int32_t arg = 1001; 
  6.   
  7. NSInvocation *inv = [NSInvocation invocationWithMethodSignature:[tapticEngine methodSignatureForSelector:selector]]; 
  8. [inv setTarget:tapticEngine]; 
  9. [inv setSelector:selector]; 
  10. [inv setArgument:&arg atIndex:2]; 
  11. [inv invoke];  

显然, 这是调用了私有 API 。

这些方法,在实际测试的时候发现,在 iPhone 7 上调用没有震动反馈,在 iPhone 6S Plus 上调用有震动反馈,在 iPhone 6 上调用 无反馈。

短震方法三 UIImpactFeedbackGenerator

iOS10 引入了一种新的、产生触觉反馈的方式, 帮助用户认识到不同的震动反馈有不同的含义 。这个功能的核心就是由 UIFeedbackGenerator 提供。Apple 对于 UIImpactFeedbackGenerator 有一篇介绍文档。

UIFeedbackGenerator 可以帮助你实现 haptic feedback。它的要求是:

  • 支持 Taptic Engine 机型 (iPhone 7 以及 iPhone 7 Plus).
  • app 需要在前台运行
  • 系统 Haptics setting 需要开启

Apple 曾表示公开了 Taptic Engine 的 API,但是鲜有文档。在搜罗了各种资料后,可以认为 UIImpactFeedbackGenerator 即 Taptic Engine 的 公开 API。

它的调用方式是:

 
  
  1. UIImpactFeedbackGenerator *generator = [[UIImpactFeedbackGenerator alloc] initWithStyle: UIImpactFeedbackStyleLight]; 
  2. [generator prepare]; 
  3. [generator impactOccurred];  

Others

观察 UIImpactFeedbackGenerator 你会发现它继承于 UIFeedbackGenerator。除了 UIImpactFeedbackGenerator 还有三种 FeedbackGenerator:

  1. UIImpactFeedbackGenerator
  2. UISelectionFeedbackGenerator
  3. UINotificationFeedbackGenerator

详情可参考 Apple 的 这篇 Reference(https://developer.apple.com/reference/uikit/uifeedbackgenerator?language=objc) 。

对于震动反馈的应用,Apple 也给出了示例场景:

 
  
  1. - (IBAction)gestureHandler:(UIPanGestureRecognizer *)sender { 
  2.   
  3. switch (sender.state) { 
  4. case UIGestureRecognizerStateBegan: 
  5.   
  6. // Instantiate a new generator. 
  7. self.feedbackGenerator = [[UISelectionFeedbackGenerator alloc] init]; 
  8.   
  9. // Prepare the generator when the gesture begins. 
  10. [self.feedbackGenerator prepare]; 
  11.   
  12. break; 
  13.   
  14. case UIGestureRecognizerStateChanged: 
  15.   
  16. // Check to see if the selection has changed... 
  17. if ([self myCustomHasSelectionChangedMethodWithTranslation:[sender translationInView: self.view]]) { 
  18.   
  19. // Trigger selection feedback. 
  20. [self.feedbackGenerator selectionChanged]; 
  21.   
  22. // Keep the generator in a prepared state. 
  23. [self.feedbackGenerator prepare]; 
  24.   
  25.   
  26. break; 
  27.   
  28. case UIGestureRecognizerStateCancelled: 
  29. case UIGestureRecognizerStateEnded: 
  30. case UIGestureRecognizerStateFailed: 
  31.   
  32. // Release the current generator. 
  33. self.feedbackGenerator = nil; 
  34.   
  35. break; 
  36.   
  37. default
  38.   
  39. // Do nothing. 
  40. break; 
  41.  

三种方法在测试机上不同的反馈结果

AUDIOSERVICESPLAYSYSTEMSOUND151915201521
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。




本文作者:佚名
来源:51CTO
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值