【问题标题】:How to prevent multiple click on a gesture?如何防止多次单击手势?
【发布时间】:2019-10-19 00:42:34
【问题描述】:

我有一个需要启动 url 的 GestureDetector。但如果手势获得多次点击,则启动会被多次调用。

在当前代码中,我试图使用状态 _isButtonTapped 来控制点击。但是 .whenComplete 在启动之前以某种方式调用?

   _isButtonTapped = false

   Widget _buildButton(String key, Text title, String url) {
    _onTapped() async {
      if (await canLaunch(url)) {
        launch(url).whenComplete(
          () => setState(() {
                _isButtonTapped = false;
              }),
        );
      }
    }

    return GestureDetector(
      onTap: () {
        _isButtonTapped ? null : _onTapped();
        setState(() {
          _isButtonTapped = true;
        });
      },
      child: Container(
        child: Padding(
          padding: EdgeInsets.all(6.0),
          child: Center(child: title),
        ),
      ),
    );
  }

【问题讨论】:

  • 添加onDoubleTap: () => null 确实可以防止双击,并使其更难执行多次点击。但并不能完全阻止它。

标签: flutter dart


【解决方案1】:

试试这个:

class _HomePageState extends State<HomePage> {
  bool _isButtonTapped = false;
  String _url = "https://google.ca";

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Container(
          color: Colors.blue,
          width: 100,
          height: 100,
          child: GestureDetector(
            onTap: () async {
              if (!_isButtonTapped) { // only allow click if it is false
                _isButtonTapped = true; // make it true when clicked
                if (await canLaunch(_url)) {
                  await launch(_url);
                  _isButtonTapped = false; // once url is launched successfully, we again make it false, allowing tapping again
                }
              }
            },
          ),
        ),
      ),
    );
  }
}

【讨论】:

  • 感谢您的回答,但这不会改变任何事情...如果 '_isButtonTapped = false;' 它确实有效在最后一行被删除。但是该按钮只能永久单击一次。它就像它没有等待的启动(_url),并且在操作完成之前将_isButtonTapped设置为false......我会尝试调查一下:)
  • 更好的解决方案
【解决方案2】:

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-11-13
    • 2018-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多