iOS中关于Taptic-Engine震动反馈的深入解析
前言
tapticengine是什么总的来说,tapticengine是苹果产品上推出的全新震动模块名称,最早出现在applewatch中,苹果iphone6s和iphone6splus也内置了tapticengine,设计上有所升级。tapticengine的全新震动模块,这颗震动模块经过特殊设计,能在短时间内达到震动的最佳状态,是普通振动马达所做不到的。taptic这个单词本身没有什么含义,比较接近的词是haptic(触觉)。
tapticengine工作原理传统的手机震动器是马达带着偏振片一起转动,从而产生震动。
大概是这个样子滴。
而tapticengine是直线电机驱动带着震块做直线往返运动。看看下面这两张蜜汁动感的示意图,你就一下子就明白它是怎么产生震动的了。
iphone6s的内置的tapticengine
applewatch的内置的tapticengine,左边集成了扬声器
taptic engine 振动模块为 apple watch 以及 iphone 6s、iphone 7 提供了 force touch 以及 3d touch,不同的屏幕操作,可以感受到不同的振动触觉效果,带来更好的用户体验。
what has happened?
上周,leader 拿着 iphone 7 打开了网易新闻,问我:『你看,你这里的下拉刷新是短震动,我们的手机数周遥控电视的时候只有长震动,产品那边问能不能用短震动』。
然后博主就去查看了一下关于短震动的方式,整个过程可以描述为——『资料真少!』。
不过最后通过一下午的搜集,最终还是总结整理出来了这份文档,也补充了自己对 iphone 6s 之后对 taptic engine 的了解。
短震方法一 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 中描述。显然,这是调用了一些私有一些属性 。
关于是否调用了私有 api,也有一些讨论,可以查看。
短震方法二 获取 _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 提供。apple 对于 uiimpactfeedbackgenerator 有一篇。
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 的 这篇 reference 。
对于震动反馈的应用,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。
代码
测试代码在这里。
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对的支持。