美文网首页
关于Flutter:震动反馈 HapticFeedback

关于Flutter:震动反馈 HapticFeedback

作者: android不是安卓 | 来源:发表于2022-05-23 19:39 被阅读0次

1. 缘起

这两天在研究 CupertinoSliverRefreshControl 组件,使用中有个小细节吸引到了我的注意。在下拉达到一定程度时,会有 weng 的一声震动感。然后翻看源码中的具体实现逻辑,在下拉量大于 refreshTriggerPullDistance 时,会触发 HapticFeedback.mediumImpact(); 方法。看到 Feedback 一词,也就知道这是震动反馈触发的方法了。


2. HapticFeedback 类的介绍

HapticFeedback 非常简单,私有构造,且提供五个静态方法,很明显是一个工具类。


其中有五个方法,从体感上来说,五种方法的震感不同,其中 vibratelightImpact 感觉上没有太大差别。mediumImpact 相对较弱,heavyImpact 很弱,最后 selectionClick 不知道是我手机问题还是什么,似乎没有震感。

vibrate ≈ lightImpact > mediumImpact > heavyImpact > selectionClick

HapticFeedback 源码中介绍提到,这里的 API 故意设计的比较简洁,只是调用平台的默认行为,并不能达到精确控制系统震动模块目的。也就是说,这里就是简单震动一下,并无法精确控制振幅、震动时长等信息。

对于 Android 来说,这五个方法分别对应 HapticFeedbackConstants 中的五个常量:

vibrate          ----   HapticFeedbackConstants.LONG_PRESS
lightImpact    ----   HapticFeedbackConstants.VIRTUAL_KEY
mediumImpact   ----   HapticFeedbackConstants.KEYBOARD_TAP
heavyImpact    ----   HapticFeedbackConstants.CONTEXT_CLICK  (API 23+)
selectionClick ----   HapticFeedbackConstants.CLOCK_TICK

对于 ios 来是 10+ 之后引入了新的震动反馈特性,很明显 FlutterHapticFeedback 的方法名称是参照 ios 来命名的。

vibrate          ----   kSystemSoundID_Vibrate
lightImpact    ----   UIImpactFeedbackGenerator-UIImpactFeedbackStyleLight (ios10+)
mediumImpact   ----   UIImpactFeedbackGenerator-UIImpactFeedbackStyleMedium (ios10+)
heavyImpact    ----   UIImpactFeedbackGenerator-UIImpactFeedbackStyleHeavy (ios10+)
selectionClick ----   UISelectionFeedbackGenerator (ios10+)

3. HapticFeedback 的使用

因为都是静态方法,所以使用也是非常简单,调用一些即可,比如:

HapticFeedback.vibrate();

下面简单写个测试界面,通过点击按钮来触发不同的震动反馈。借此也来说一下,如何优雅地实现这种若干个需要触发事件的按钮。可能有人看到这个界面,就想到在 Wrap 放一个个的 ElevatedButton 不就行了吗。如果直接一个个塞进去,代码会很长,而且不易管理。

其实这里的数据关系是 字符串和方法(函数)的映射 ,而 方法(函数) 本身也可以作为对象。所以可以使用 Map 来维护数据,为了方便表示函数类型,可以通过 typedef 进行声明,比如下面的 VoidAsyncFunction

typedef VoidAsyncFunction = Future<void> Function();

final Map<String, VoidAsyncFunction> feedbackMap = const {
  'vibrate': HapticFeedback.vibrate,
  'heavyImpact': HapticFeedback.heavyImpact,
  'mediumImpact': HapticFeedback.mediumImpact,
  'lightImpact': HapticFeedback.lightImpact,
  'selectionClick': HapticFeedback.selectionClick,
};

这样在 Wrap 中,通过 feedbackMap 来遍历 key 列表,生成 ElevatedButton 即可。其中 feedbackMap[name] 就是代表字符串名称对应的函数对象。

Wrap(
  spacing: 5,
  runSpacing: 5,
  alignment: WrapAlignment.center,
  children: feedbackMap.keys
      .map((String name) => ElevatedButton(
          onPressed: feedbackMap[name],
          child: Text(name),
        ),
      ).toList(),
),


4. HapticFeedback 中的方法是异步的

HapticFeedback 中的方法是通过 SystemChannels.platform 执行平台方法实现功能的。也就是说,触发 vibrate 并不会立刻震动,向平台通道发送消息是个不确定时长的异步任务。

static Future<void> vibrate() async {
  await SystemChannels.platform.invokeMethod<void>('HapticFeedback.vibrate');
}

如何你需要确切在震动之后才触发某段逻辑,可以通过 await 来等待异步任务完成。比如下面连续四次,间隔 500 ms 的震动。需要在前一次震动方法完成,才能开始下次震动。

void run() async {
  Duration duration = const Duration(milliseconds: 500);
  await HapticFeedback.vibrate();
  await Future.delayed(duration);
  await HapticFeedback.heavyImpact();
  await Future.delayed(duration);
  await HapticFeedback.mediumImpact();
  await Future.delayed(duration);
  await HapticFeedback.lightImpact();
}

不过一般来说,并没有必要非常精确地知道震动方法完成的时机,因为这个时间非常短,在 10 ms 左右。像下拉到一定高度给出震动感,并不是很在意确切的时间。

int tag = DateTime.now().millisecondsSinceEpoch;
await HapticFeedback.vibrate();
int now = DateTime.now().millisecondsSinceEpoch;
print(now-tag);


5. HapticFeedback 中各种震动在源码中的使用

首先在 androidfuchsia 中,长按事件会触发 vibrate 震动。iOS 平台一般不会对长按事件进行反馈。

另外,注意一点,在 InkWellTooltip 组件中才会触发 forLongPress ,也就是说 GestureDetector 的长按事件是没有震动反馈的。


lightImpactCupertinoSwitch 组件中被使用,只有在 iOS 平台才会有反馈。


mediumImpactCupertinoSliverRefreshControlCupertinoScrollbar 组件中被使用:


selectionClickCupertinoPickerLongPressDraggableCupertinoContextMenu 中被使用。


最后,heavyImpact 方法没有在框架中被使用。这就是 HapticFeedback 关于震动反馈的一些小知识,本文就到这里,谢谢观看 ~

作者:张风捷特烈
链接:https://juejin.cn/post/7100733430383673381
来源:稀土掘金

相关文章

  • 关于Flutter:震动反馈 HapticFeedback

    1. 缘起 这两天在研究 CupertinoSliverRefreshControl 组件,使用中有个小细节吸引到...

  • 系统震动or震动反馈

    一.系统震动 1.AudioServicesPlaySystemSound() 系统震动是在iOS10.0之前存在...

  • iOS 震动反馈

    http://zhoulingyu.com/2017/01/16/iOS——关于-Taptic-Engine-震动反馈/

  • iOS 震动反馈(UIFeedbackGenerator)和系统

    震动反馈(UIFeedbackGenerator) 震动反馈是iOS 10之后出的新特性,相比于之前的系统震动Au...

  • 手机马达、方向盘4向调节与APP黑夜模式

    我日常比较喜欢看手机评测,其中发现数码区up主在评测手机的时候会经常强调一个关于手机震动感反馈的问题。震动感反馈取...

  • iOS震动反馈

    长震动 支持iPhone基本机型,支持iOS9注:用户在“系统设置”中关闭了振动功能,此震动会失效。 短震动一 支...

  • iOS震动反馈

    之前的手机系统要用到的震动接口是AudioServicesPlaySystemSound,但这个震动幅度比较大,如...

  • Android震动反馈

    Android手机在输入法的时候可以设置一个轻震动反馈,这个反馈也可以用接口调用到需要用到震动反馈的地方。 这个震...

  • ios的震动反馈

    最近写 ios TableView 加入长按的手势后,希望在 cell 长按弹窗的同时加入震动反馈效果。 查询后发...

  • MJRefresh增加震动反馈

    MJRefresh增加震动反馈 发现有的app在下拉刷新的时候有一下震动反馈,感觉用户体验很棒,所以想在现有的项目...

网友评论

      本文标题:关于Flutter:震动反馈 HapticFeedback

      本文链接:https://www.haomeiwen.com/subject/kmfdprtx.html