Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
ff5b0e14
Unverified
Commit
ff5b0e14
authored
Aug 07, 2023
by
xhzq233
Committed by
GitHub
Aug 07, 2023
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
CupertinoContextMenu improvement (#131030)
Fixes overlapping gestures in CupertinoContextMenu's subtree
parent
1a31682e
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
85 additions
and
9 deletions
+85
-9
context_menu.dart
packages/flutter/lib/src/cupertino/context_menu.dart
+14
-9
context_menu_test.dart
packages/flutter/test/cupertino/context_menu_test.dart
+71
-0
No files found.
packages/flutter/lib/src/cupertino/context_menu.dart
View file @
ff5b0e14
...
...
@@ -6,7 +6,7 @@ import 'dart:math' as math;
import
'dart:ui'
as
ui
;
import
'package:flutter/foundation.dart'
;
import
'package:flutter/gestures.dart'
show
kMinFlingVelocity
;
import
'package:flutter/gestures.dart'
;
import
'package:flutter/scheduler.dart'
;
import
'package:flutter/services.dart'
show
HapticFeedback
;
import
'package:flutter/widgets.dart'
;
...
...
@@ -480,6 +480,7 @@ class _CupertinoContextMenuState extends State<CupertinoContextMenu> with Ticker
OverlayEntry
?
_lastOverlayEntry
;
_ContextMenuRoute
<
void
>?
_route
;
final
double
_midpoint
=
CupertinoContextMenu
.
animationOpensAt
/
2
;
late
final
TapGestureRecognizer
_tapGestureRecognizer
;
@override
void
initState
()
{
...
...
@@ -490,13 +491,20 @@ class _CupertinoContextMenuState extends State<CupertinoContextMenu> with Ticker
upperBound:
CupertinoContextMenu
.
animationOpensAt
,
);
_openController
.
addStatusListener
(
_onDecoyAnimationStatusChange
);
_tapGestureRecognizer
=
TapGestureRecognizer
()
..
onTapCancel
=
_onTapCancel
..
onTapDown
=
_onTapDown
..
onTapUp
=
_onTapUp
..
onTap
=
_onTap
;
}
void
_listenerCallback
()
{
if
(
_openController
.
status
!=
AnimationStatus
.
reverse
&&
_openController
.
value
>=
_midpoint
&&
widget
.
enableHapticFeedback
)
{
HapticFeedback
.
heavyImpact
();
_openController
.
value
>=
_midpoint
)
{
if
(
widget
.
enableHapticFeedback
)
{
HapticFeedback
.
heavyImpact
();
}
_tapGestureRecognizer
.
resolve
(
GestureDisposition
.
accepted
);
_openController
.
removeListener
(
_listenerCallback
);
}
}
...
...
@@ -663,11 +671,8 @@ class _CupertinoContextMenuState extends State<CupertinoContextMenu> with Ticker
Widget
build
(
BuildContext
context
)
{
return
MouseRegion
(
cursor:
kIsWeb
?
SystemMouseCursors
.
click
:
MouseCursor
.
defer
,
child:
GestureDetector
(
onTapCancel:
_onTapCancel
,
onTapDown:
_onTapDown
,
onTapUp:
_onTapUp
,
onTap:
_onTap
,
child:
Listener
(
onPointerDown:
_tapGestureRecognizer
.
addPointer
,
child:
TickerMode
(
enabled:
!
_childHidden
,
child:
Visibility
.
maintain
(
...
...
packages/flutter/test/cupertino/context_menu_test.dart
View file @
ff5b0e14
...
...
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'package:clock/clock.dart'
;
import
'package:flutter/cupertino.dart'
;
import
'package:flutter/foundation.dart'
;
import
'package:flutter/gestures.dart'
;
...
...
@@ -810,4 +811,74 @@ void main() {
expect
(
right
.
dx
,
lessThan
(
left
.
dx
));
});
});
testWidgets
(
'Conflicting gesture detectors'
,
(
WidgetTester
tester
)
async
{
int
?
onPointerDownTime
;
int
?
onPointerUpTime
;
bool
insideTapTriggered
=
false
;
// The required duration of the route to be pushed in is [500, 900]ms.
// 500ms is calculated from kPressTimeout+_previewLongPressTimeout/2.
// 900ms is calculated from kPressTimeout+_previewLongPressTimeout.
const
Duration
pressDuration
=
Duration
(
milliseconds:
501
);
int
now
()
=>
clock
.
now
().
millisecondsSinceEpoch
;
await
tester
.
pumpWidget
(
Listener
(
onPointerDown:
(
PointerDownEvent
event
)
=>
onPointerDownTime
=
now
(),
onPointerUp:
(
PointerUpEvent
event
)
=>
onPointerUpTime
=
now
(),
child:
CupertinoApp
(
home:
Align
(
child:
CupertinoContextMenu
(
actions:
const
<
CupertinoContextMenuAction
>[
CupertinoContextMenuAction
(
child:
Text
(
'CupertinoContextMenuAction'
),
),
],
child:
GestureDetector
(
onTap:
()
=>
insideTapTriggered
=
true
,
child:
Container
(
width:
200
,
height:
200
,
key:
const
Key
(
'container'
),
color:
const
Color
(
0xFF00FF00
),
),
),
),
),
),
));
// Start a press on the child.
final
TestGesture
gesture
=
await
tester
.
createGesture
();
await
gesture
.
down
(
tester
.
getCenter
(
find
.
byKey
(
const
Key
(
'container'
))));
// Simulate the actual situation:
// the user keeps pressing and requesting frames.
// If there is only one frame,
// the animation is mutant and cannot drive the value of the animation controller.
for
(
int
i
=
0
;
i
<
100
;
i
++)
{
await
tester
.
pump
(
pressDuration
~/
100
);
}
await
gesture
.
up
();
// Await pushing route.
await
tester
.
pumpAndSettle
();
// Judge whether _ContextMenuRouteStatic present on the screen.
final
Finder
routeStatic
=
find
.
byWidgetPredicate
(
(
Widget
w
)
=>
'
${w.runtimeType}
'
==
'_ContextMenuRouteStatic'
,
);
// The insideTap and the route should not be triggered at the same time.
if
(
insideTapTriggered
)
{
// Calculate the actual duration.
final
int
actualDuration
=
onPointerUpTime
!
-
onPointerDownTime
!;
expect
(
routeStatic
,
findsNothing
,
reason:
'When actualDuration(
$actualDuration
) is in the range of 500ms~900ms, '
'which means the route is pushed, '
'but insideTap should not be triggered at the same time.'
);
}
else
{
// The route should be pushed when the insideTap is not triggered.
expect
(
routeStatic
,
findsOneWidget
);
}
});
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment