Flutter 防止重复快速点击

950 阅读1分钟

App使用中避免不了被某些用户疯狂点击一些按钮,造成页面多次跳转或者接口频繁调用,这样很可能对程序造成一些bug,今天我们来处理一下在Flutter中如何防止重复快速点

DebounceButton.gif

我们以TextButton为例,对TextButton进行封装处理。

思路:记录第一点击时间,再次点击后判断与第一次的时间差,如果大于我们定义的防抖时间那么就执行点击,否则拦截此次点击。

  1. 封装 DebounceButton
class DebounceButton extends StatelessWidget {
    final VoidCallback? onPressed;
    final Widget? child;
    final int milliseconds;
    final VoidCallback? onLongPress;
    final ValueChanged<bool>? onHover;
    final ValueChanged<bool>? onFocusChange;
    final ButtonStyle? style;
    final FocusNode? focusNode;
    final bool autofocus;

    final Clip clipBehavior;
    final MaterialStatesController? statesController;

    DebounceButton(
        {Key? key,
            required this.onPressed,
            required this.child,
            this.milliseconds = 800,
            this.onLongPress,
            this.onHover,
            this.onFocusChange,
            this.style,
            this.focusNode,
            this.autofocus = false,
            this.clipBehavior = Clip.none,
            this.statesController})
        : super(key: key);

    @override
    Widget build(BuildContext context) {
        return TextButton(
            onPressed: onPressed == null
                ? null
                : onPress(fun: onPressed, milliseconds: milliseconds),
            onLongPress: onLongPress,
            onHover: onHover,
            onFocusChange: onFocusChange,
            style: style,
            focusNode: focusNode,
            autofocus: autofocus,
            clipBehavior: clipBehavior,
            statesController: statesController,
            child: child!,
        );
    }

    final TimeData timeData = TimeData();

    bool doubleClick(int milliseconds) {
      DateTime? lastPressedAt = timeData.lastPressedAt;
        if (lastPressedAt == null ||
            DateTime.now().difference(lastPressedAt) > Duration(milliseconds: milliseconds)) {
            timeData.lastPressedAt = DateTime.now();
            return false;
        }
        return true;
    }

    Function() onPress({Function()? fun, int milliseconds = 800}) {
        return () {
            if (doubleClick(milliseconds)) {
                return;
            }
            fun?.call();
        };
    }

}
class TimeData{
  DateTime? lastPressedAt;
}

上面其实就是一个 TextButton 。看似有不少的参数,其实只有 milliseconds 参数是我们自定义的一个防抖时间,其他参数都是TextButton 原有参数。

  1. 使用就比较简单了,和 TextButton 使用是一致的。
 DebounceButton(
    onPressed: () {
              Printer.error('防抖点击: ${debounceCount++}');
            },
            child: const Text(
              '防抖',
              style: TextStyle(color: Colors.white),
            ),
          ),

好了,经过前面的一顿操作之后就可以防止重复快速点击!!!

不足之处,欢迎大家指正。