如何防止对 Flutter Inkwell 进行多次触摸

How to prevent multiple touch on Flutter Inkwell

我是 flutter 的新手,我有一个计数器按钮,我想防止它被多次触摸。

Tap 函数在 Inkwell 组件 (onTap: () => counterBloc.doCount(context)) 下定义。

如果我 运行 这个应用程序并进行多点触控,计数器会快速上升,但我不希望它发生。有什么想法吗?

下面是我的代码:

  Expanded(
  child: Container(
    padding: EdgeInsets.only(right: 16),
    alignment: Alignment.centerRight,
    child: InkWell(
      onTap: () => counterBloc.doCount(context),
      child: Stack(
        alignment: Alignment.center,
        children: <Widget>[
          Image.asset("assets/images/home/tap.png", scale: 11,),
          StreamBuilder(
            initialData: 0,
            stream: counterBloc.counterStream,
            builder: (BuildContext ctx, AsyncSnapshot<int> snapshot){
              return Text("${snapshot.data}",style: TextStyle(color: Colors.white, fontSize: 120),);
            },
          ),
        ],
      )
    )
  )
)

你可以使用 AbsorbPointer

AbsorbPointer(
  absorbing: !enabled,
  child: InkWell(
    onTap: (){
      print('buttonClicked');
      setState(() {
        enabled = false;
      });
    },
    child: Container(
      width: 50.0,
      height: 50.0,
      color: Colors.red,
    ),
  ),
),

当你想再次启用按钮时,将 enabled 设置为 true,不要忘记用 setState

包裹它

另一种选择是使用 去抖动 来防止这种行为,即 easy_debounce, or .

试试这个?它应该可以解决您的问题。

class SafeOnTap extends StatefulWidget {
  SafeOnTap({
    Key? key,
    required this.child,
    required this.onSafeTap,
    this.intervalMs = 500,
  }) : super(key: key);
  final Widget child;
  final GestureTapCallback onSafeTap;
  final int intervalMs;

  @override
  _SafeOnTapState createState() => _SafeOnTapState();
}

class _SafeOnTapState extends State<SafeOnTap> {
  int lastTimeClicked = 0;

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () {
        final now = DateTime.now().millisecondsSinceEpoch;
        if (now - lastTimeClicked < widget.intervalMs) {
          return;
        }
        lastTimeClicked = now;
        widget.onSafeTap();
      },
      child: widget.child,
    );
  }
}

如果需要,您可以包装任何类型的小部件。

class HomeScreen extends StatefulWidget {
  const HomeScreen({Key? key}) : super(key: key);

  @override
  _HomeScreenState createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Center(
          child: Column(
            children: [
              // every click need to wait for 500ms
              SafeOnTap(
                onSafeTap: () => log('500ms'),
                child: Container(
                  width: double.infinity,
                  height: 200,
                  child: Center(child: Text('500ms click me')),
                ),
              ),
              // every click need to wait for 2000ms
              SafeOnTap(
                intervalMs: 2000,
                onSafeTap: () => log('2000ms'),
                child: Container(
                  width: double.infinity,
                  height: 200,
                  child: Center(child: Text('2000ms click me')),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

您也可以使用IgnorePointer

IgnorePointer(
ignoring: !isEnabled
child: yourChildWidget
)

当您禁用该组件时,它会开始忽略小部件边界内的触摸。

我个人不会依赖 setState,我会采用像这样的简单解决方案:

Widget createMultiClickPreventedButton(String text, VoidCallback clickHandler) {
  var clicked = false;
  return ElevatedButton(
  child: Text(text),
  onPressed: () {
    if (!clicked) {
      clicked = true;
      clickHandler.call();
    }
  });
}