搜索插件、代码仓与 APP 分类

tap_debouncer 封面
插件详情v2.2.0

tap_debouncer

点击去抖动简化小部件。将您的按钮小部件包裹在 TapDebounce 小部件中,当点击回调正在进行时,任何点击都将被禁用。

AndroidiOSWebmacOSWindowsLinux
近 30 天下载
1.9万
喜欢数
120
Pub 分数
160

安装插件

flutter pub add tap_debouncer

插件介绍

基于插件公开信息、社区数据与项目使用情况整理的选型参考。

TapDebounce 是一个 Flutter 包,可简化防止在小部件(尤其是按钮)上重复点击的问题。通过将小部件包裹在 TapDebounce 小部件中,可在点击回调执行期间禁用进一步的点击,从而降低意外多次提交的风险。适用于表单、操作或任何可能因快速点击而出现问题的交互元素。支持所有主要平台,并可无缝集成到现有的 Flutter 项目中。

适合场景

  • 防止重复表单提交
  • 避免在支付流程中快速点击按钮
  • 在动作密集型界面中提升用户体验
  • 减少意外的状态更改
  • 安全处理缓慢的网络响应
  • 防止意外的双击

主要特点

  • 回调期间自动禁用点击
  • 简单的环绕集成
  • 跨平台支持
  • 最小化样板代码
  • 可配置的去抖持续时间
  • 适用于任何小部件

适合对象

  • 寻求快速点击保护的开发者
  • 高点击风险的表单和操作 UI
  • 需要可靠用户交互控制的应用程序
  • 注重用户体验一致性的团队
  • 频繁按钮交互的项目

使用建议

  • 如果回调立即完成,则不会阻止点击
  • 长时间运行的任务可能需要手动重置
  • 仅限点击事件
  • 禁用状态无内置反馈
  • 不适合复杂手势识别
  • 在异步工作流中需要谨慎处理

原始 README

以下为关联源码仓库的 README 原文快照,最新内容请访问源码仓库。

Analyze and tests status

Coverage Status

MIT License

Description

Tap debounce simplifying widget. Wrap your button widget in TapDebounce widget and any taps will be disabled while tap callback is in progress.

Manual

Initial code

Assume your code with some button look like this:

//...
child: RaisedButton(
  color: Colors.blue,
  disabledColor: Colors.grey,
  onPressed: () async => await someLongOperation(), // your tap handler
  child: const Text('Short'),
  );
//...

and you do not want user to be able to press the button again several times and start other someLongOperation functions. Example is a Navigator pop function - it can take a few hundred of millis to navigate and user can press the button several times, and that will lead to undesired pop several screens back instead of one.

Wrap code to TapDebouncer

Wrap this code to Debouncer and move RaisedButton onPressed contents to Debouncer onTap:

//...
child: TapDebouncer(
  onTap: () async => await someLongOperation(), // your tap handler moved here
  builder: (BuildContext context, TapDebouncerFunc? onTap) {
    return RaisedButton(
      color: Colors.blue,
      disabledColor: Colors.grey,
      onPressed: onTap,  // It is just onTap from builder callback
      child: const Text('Short'),
    );
  },
),
//...

Debouncer will disable the RaisedButton by setting onPressed to null while onTap is being executed.

Add delay after tap process

You can add optional delay to be sure that the button is disabled some time after someOperation is called.

//...
onTap: () async {
    await someOperation();
    
    await Future<void>.delayed(const Duration(milliseconds: 1000));
},
//...
Use cooldown instead of delay

You can fill optional cooldown field with some Duration and avoid adding of Future.delayed at the end of onTap callback, this will be done automatically:

//...
child: TapDebouncer(
  cooldown: const Duration(milliseconds: 1000),
  onTap: () async => await someLongOperation(), // your tap handler moved here
  builder: (BuildContext context, TapDebouncerFunc? onTap) {
    return RaisedButton(
      color: Colors.blue,
      disabledColor: Colors.grey,
      onPressed: onTap,  // It is just onTap from builder callback
      child: const Text('Short'),
    );
  },
),
//...

Then your onTap could be changed to this:

//...
onTap: () async => await someOperation(),
//...
Cooldown behavior with exception

If someOperation will raise exception cooldown delay will also work, after exception.

Change look of busy widget (waiting for tap complete)

You can inspect value of onTap and change look of your widget:

//...
builder: (BuildContext context, TapDebouncerFunc? onTap) {
  return RaisedButton(
    color: Colors.blue,
    onPressed: onTap,
    // variant with manual test onTap for null in builder
    child: onTap == null
        ? const Text('Wait...')
        : const Text('Short'),
  );
},
//...

Also you can use waitBuilder method to build new busy widget:

//...
builder: (BuildContext context, TapDebouncerFunc? onTap) {
//...
},
// variant with using waitBuilder instead of test onTap for null
waitBuilder: (BuildContext context, Widget child) {
  return Stack(
    children: <Widget>[
      child,
      const Center(child: CircularProgressIndicator()),
    ],
  );
},
//...

waitBuilder will return original widget (built with onTap == null) as child

Example

See example application for details:

Example of button disabled after tap

所属分类

源码仓库

使用此插件的项目

暂无相关数据。