-
Notifications
You must be signed in to change notification settings - Fork 30.2k
In GestureDetector, HorizontalDragGestureRecognizer takes precedence over ScaleGestureRecognizer #137189
Copy link
Copy link
Open
Labels
P3Issues that are less important to the Flutter projectIssues that are less important to the Flutter projectf: gesturesflutter/packages/flutter/gestures repository.flutter/packages/flutter/gestures repository.found in release: 3.13Found to occur in 3.13Found to occur in 3.13found in release: 3.16Found to occur in 3.16Found to occur in 3.16frameworkflutter/packages/flutter repository. See also f: labels.flutter/packages/flutter repository. See also f: labels.has reproducible stepsThe issue has been confirmed reproducible and is ready to work onThe issue has been confirmed reproducible and is ready to work onteam-frameworkOwned by Framework teamOwned by Framework teamtriaged-frameworkTriaged by Framework teamTriaged by Framework team
Description
Is there an existing issue for this?
- I have searched the existing issues
- I have read the guide to filing a bug
Steps to reproduce
- Create a demo app with the code below
- Try to do a scale (two finger pinch zoom) gesture in the center of the screen
Expected results
If both scale and drag events are defined, and I try to do a scale (pinch zoom) gesture, I expect the scale event to fire.
Actual results
Most of the time the drag event fires instead. Sometimes the scale event does fire.
Code sample
Code sample
import 'package:flutter/material.dart';
import 'package:flutter/gestures.dart';
void main() {
debugPrintGestureArenaDiagnostics = true;
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.title),
),
body: GestureDetector(
onTap: () {
print("Tapped on full screen!");
},
onScaleStart: (details) {
print('onScaleStart');
},
onScaleUpdate: (details) {
print('onScaleUpdate');
},
onScaleEnd: (_) async {
print('onScaleEnd');
},
onHorizontalDragStart: (_) {
print('onHorizontalDragStart');
},
onHorizontalDragEnd: (_) async {
print('onHorizontalDragEnd');
},
onHorizontalDragUpdate: (DragUpdateDetails details) async {
print('onHorizontalDragUpdate');
},
onTapDown: (TapDownDetails details) {
print('onTapDown');
},
onTapCancel: () async {
print('onTapCancel');
},
child: Container(
// Set the size to occupy the full screen
width: double.infinity,
height: double.infinity,
color: Colors.red, // Background color
),
),
);
}
}Screenshots or Video
Screenshots / Video demonstration
[Upload media here]
Logs
Logs
The debug console shows:
I/flutter (13620): Gesture arena 1 ❙ ★ Opening new gesture arena.
I/flutter (13620): Gesture arena 1 ❙ Adding: TapGestureRecognizer#51f6a(debugOwner: GestureDetector, state: ready, button: 1)
I/flutter (13620): Gesture arena 1 ❙ Adding: HorizontalDragGestureRecognizer#7c597(debugOwner: GestureDetector, start behavior: start)
I/flutter (13620): Gesture arena 1 ❙ Adding: ScaleGestureRecognizer#27a81(debugOwner: GestureDetector)
I/flutter (13620): Gesture arena 1 ❙ Closing with 3 members.
I/flutter (13620): Gesture arena 2 ❙ ★ Opening new gesture arena.
I/flutter (13620): Gesture arena 2 ❙ Adding: TapGestureRecognizer#51f6a(debugOwner: GestureDetector, state: possible, button: 1)
I/flutter (13620): Gesture arena 2 ❙ Adding: HorizontalDragGestureRecognizer#7c597(debugOwner: GestureDetector, start behavior: start)
I/flutter (13620): Gesture arena 2 ❙ Adding: ScaleGestureRecognizer#27a81(debugOwner: GestureDetector)
I/flutter (13620): Gesture arena 2 ❙ Closing with 3 members.
I/flutter (13620): Gesture arena 1 ❙ Accepting: HorizontalDragGestureRecognizer#7c597(debugOwner: GestureDetector, start behavior: start)
I/flutter (13620): Gesture arena 1 ❙ Self-declared winner: HorizontalDragGestureRecognizer#7c597(debugOwner: GestureDetector, start behavior: start)
I/flutter (13620): onHorizontalDragStart
I/flutter (13620): Gesture arena 2 ❙ Accepting: HorizontalDragGestureRecognizer#7c597(debugOwner: GestureDetector, start behavior: start)
I/flutter (13620): Gesture arena 2 ❙ Self-declared winner: HorizontalDragGestureRecognizer#7c597(debugOwner: GestureDetector, start behavior: start)
106
I/flutter (13620): onHorizontalDragUpdate
I/flutter (13620): onHorizontalDragEnd
meaning DoubleTapGestureRecognizer for some reason declares itself a winner, and the ScaleGestureRecognizer loses.
Flutter Doctor output
Doctor output
[✓] Flutter (Channel stable, 3.13.8, on Microsoft Windows [Version 10.0.22621.2428], locale en-US)
[✓] Windows Version (Installed version of Windows is version 10 or higher)
[✓] Android toolchain - develop for Android devices (Android SDK version 33.0.2)
[✓] Android Studio (version 2022.3)
[✓] VS Code, 64-bit edition (version 1.83.1)
[✓] Connected device (1 available)
[✓] Network resources
• No issues found!Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
P3Issues that are less important to the Flutter projectIssues that are less important to the Flutter projectf: gesturesflutter/packages/flutter/gestures repository.flutter/packages/flutter/gestures repository.found in release: 3.13Found to occur in 3.13Found to occur in 3.13found in release: 3.16Found to occur in 3.16Found to occur in 3.16frameworkflutter/packages/flutter repository. See also f: labels.flutter/packages/flutter repository. See also f: labels.has reproducible stepsThe issue has been confirmed reproducible and is ready to work onThe issue has been confirmed reproducible and is ready to work onteam-frameworkOwned by Framework teamOwned by Framework teamtriaged-frameworkTriaged by Framework teamTriaged by Framework team