如何在Flutter中防止多次点击Inkwell

8

我刚开始接触Flutter,并且我有一个计数器按钮,我想防止它被多次点击。

触摸功能是在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),);
            },
          ),
        ],
      )
    )
  )
)
6个回答

10

你可以使用 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中。


4

试试这个?它应该能解决你的问题。

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')),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

0

你也可以使用 Stream 来创建计数器,仅在去抖动的轻拍上进行计数。

final BehaviourSubject onTapStream = BehaviourSubject()

@override
void initState() {
  super.initState();

  // Debounce your taps here
  onTapStream.debounceTime(const Duration(milliseconds: 300)).listen((_) {
      
     // Do something on tap
     print(1);
  });
}


0

我个人不会依赖setState,而是选择像这样的简单方案:

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

0

0

你也可以使用IgnorePointer

IgnorePointer(
ignoring: !isEnabled
child: yourChildWidget
)

当你禁用组件时,它会开始忽略小部件范围内的触摸。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接