はじめに
Disable Multi Touch On A Widget In Flutterを元にした記事になります。
FlutterでListViewなどで画面を作ってそれぞれのItemをタップして詳細画面に遷移させるようなものを作ったとき、そのままでは2本以上の指で複数のItemを同時にタップして一度に複数の画面をPushして遷移してしまいます。
そこで、同時に複数のItemをタップしたときもどれか1つだけ反応するようにしたいとします。
実装
SingleTouchContainer
というWidgetを作ってみました。このWidgetでWrapすればchildのWidgetでは同時タップできずに、同時タップしたときに同時に複数のItemでRippleなどのタップエフェクトも効かなくなります。
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
/// [reference](https://stacksecrets.com/flutter/disable-multi-touch-on-a-widget-in-flutter)
class SingleTouchContainer extends StatelessWidget {
const SingleTouchContainer({
Key? key,
required this.child,
}) : super(key: key);
final Widget child;
@override
Widget build(BuildContext context) {
return RawGestureDetector(
gestures: <Type, GestureRecognizerFactory>{
_SingleTouchRecognizer:
GestureRecognizerFactoryWithHandlers<_SingleTouchRecognizer>(
_SingleTouchRecognizer.new,
(_) {},
),
},
child: child,
);
}
}
class _SingleTouchRecognizer extends OneSequenceGestureRecognizer {
int _p = 0;
@override
void addAllowedPointer(PointerDownEvent event) {
startTrackingPointer(event.pointer);
if (_p == 0) {
resolve(GestureDisposition.rejected);
_p = event.pointer;
} else {
resolve(GestureDisposition.accepted);
}
}
@override
String get debugDescription => 'single touch recognizer';
@override
void didStopTrackingLastPointer(int pointer) {}
@override
void handleEvent(PointerEvent event) {
if (!event.down && event.pointer == _p) {
_p = 0;
}
}
}
使うとき
@override
Widget build(BuildContext context) {
return SingleTouchContainer(
child: ListView(
...
),
);
}
参考