Flutter 检测三次敲击

eqoofvh9  于 2023-05-30  发布在  Flutter
关注(0)|答案(6)|浏览(166)

虽然GestureDetector只内置了检测双击的功能,但我希望能够在Flutter小部件中检测三次点击(甚至更多)。
什么是最简单的方法来检测一个小工具上的三次点击?
(我想不断地点击屏幕的一部分来解锁一些开发者选项)

vyu0f0g1

vyu0f0g11#

我对这个有点懒,实际上并不难

// init
int lastTap = DateTime.now().millisecondsSinceEpoch;
int consecutiveTaps = 0;

GestureDetector(
        onTap: () {
          int now = DateTime.now().millisecondsSinceEpoch;
          if (now - lastTap < 1000) {
            print("Consecutive tap");
            consecutiveTaps ++;
            print("taps = " + consecutiveTaps.toString());
            if (consecutiveTaps > 4){
              // Do something
            }
          } else {
            consecutiveTaps = 0;
          }
          lastTap = now;
        },
        child: ...
)
qq24tv8q

qq24tv8q2#

我尝试了这里提到的方法,但它对我不起作用。GestureDetector onTap仅被调用一次,而与点击次数无关。可能有些东西已经改变了Flutter(我在测试频道)。然而,我深入研究了flutter的源代码,并得出了解决方案(https://api.flutter.dev/flutter/gestures/SerialTapGestureRecognizer-class.html):

import "package:flutter/gestures.dart";
import 'package:flutter/material.dart';

RawGestureDetector(
  gestures: {
    SerialTapGestureRecognizer:
        GestureRecognizerFactoryWithHandlers<SerialTapGestureRecognizer>(
            SerialTapGestureRecognizer.new,
            (SerialTapGestureRecognizer instance) {
      instance.onSerialTapDown = (SerialTapDownDetails details) {
         if (details.count == 3) print('Consecutive tap 3');
      };
    })
  },

  //  child: // your widget,
);
pbossiut

pbossiut3#

我采取了一种不同的方法。我设置了一个Timer,而不是必须比较时间戳,它将重置被点击的状态。但每次有一个水龙头,旧计时器被取消。

Timer? devPageClickTimer;
num devPageTapped = 0;
final devPageTapGoal = 5;

GestureDetector(
  onTap: () {
    devPageTapped++;
    if (devPageTapped >= devPageTapGoal) {
      router.push(const DeveloperRoute());
    }

    if (devPageClickTimer != null) {
      devPageClickTimer!.cancel();
    }

    devPageClickTimer = Timer(const Duration(milliseconds: 200), () => devPageTapped = 0);
},
eimct9ow

eimct9ow4#

我已经尝试过这种方法,减少超时,并与两次和三次点击

int lastTap = DateTime.now().millisecondsSinceEpoch;
int consecutiveTaps = 1;
GestureDetector(
      onTap: () {
        int now = DateTime.now().millisecondsSinceEpoch;
        if (consecutiveTaps == 1) {
          print("taps = " + consecutiveTaps.toString());
          lastTap = now;
        }
        if (now - lastTap < 300) {
          print("Consecutive tap");
          consecutiveTaps++;
          print("taps = " + consecutiveTaps.toString());
          if (consecutiveTaps == 3) {
            print("Consecutive tap 3");
          } else if (consecutiveTaps == 2) {
             print("Consecutive tap 2");
          }
        } else {
          consecutiveTaps = 1;
        }
        lastTap = now;
      },
      child: \\child);
bbuxkriu

bbuxkriu5#

相关解决方案。这是一个灵活的可重用的多点点击小部件,它基于报告原始指针事件的监听器小部件:

class AppMultipleTap extends StatefulWidget {
  final Widget child;
  final VoidCallback onMultipleTap;
  final int taps;
  final Duration duration;

  const AppMultipleTap({
    super.key,
    required this.child,
    required this.onMultipleTap,
/// feel free to override these values
    this.taps = 3,
    this.duration = const Duration(milliseconds: 600),
  });

  @override
  State<AppMultipleTap> createState() => _AppMultipleTapState();
}

class _AppMultipleTapState extends State<AppMultipleTap> {
/// in _count we store current number of taps
  int _count = 0;
  Timer? _timer;

  @override
  Widget build(BuildContext context) {
    return Listener(
      onPointerDown: (_) {
        if (_timer == null) _startTimer();
        _count++;
      },
      child: widget.child,
    );
  }

  void _startTimer() {
    _timer = Timer(widget.duration, () {
/// you can change this condition to ==, if you need 100% match
      if (_count >= widget.taps) {
        widget.onMultipleTap.call();
      }
      _timer = null;
      _count = 0;
    });
  }
}

你可以这样使用它:

@override
  Widget build(BuildContext context) {
    return AppMultipleTap(
      onMultipleTap: /// Do some action
cxfofazt

cxfofazt6#

我喜欢这种简单的方法,没有那么多嵌套的if块。

// Variables in the state class
var startTap = timeNow;
var consecutiveTaps = 0;
static const int serialTaps = 4;
static const int tapDurationInMs = 1000;
static int get timeNow => DateTime.now().millisecondsSinceEpoch;

// Build method
GestureDetector(
  onTap: () {
    final now = timeNow;
    final userExceededTapDuration = now - startTap > tapDurationInMs;

    if (userExceededTapDuration) {
      consecutiveTaps = 0;
      startTap = now;
    }

    consecutiveTaps++;

    if (consecutiveTaps == serialTaps) {
      // widget.onTap();
    }
  },
);

相关问题