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
afdfc56b
Unverified
Commit
afdfc56b
authored
May 20, 2022
by
Bruno Leroux
Committed by
GitHub
May 20, 2022
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix tooltips don't dismiss when using TooltipTriggerMode.tap (#103960)
parent
0428f421
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
94 additions
and
9 deletions
+94
-9
tooltip.dart
packages/flutter/lib/src/material/tooltip.dart
+21
-8
tooltip_test.dart
packages/flutter/test/material/tooltip_test.dart
+73
-1
No files found.
packages/flutter/lib/src/material/tooltip.dart
View file @
afdfc56b
...
@@ -216,11 +216,13 @@ class Tooltip extends StatefulWidget {
...
@@ -216,11 +216,13 @@ class Tooltip extends StatefulWidget {
/// Defaults to 0 milliseconds (tooltips are shown immediately upon hover).
/// Defaults to 0 milliseconds (tooltips are shown immediately upon hover).
final
Duration
?
waitDuration
;
final
Duration
?
waitDuration
;
/// The length of time that the tooltip will be shown after a long press
/// The length of time that the tooltip will be shown after a long press is
/// is released or mouse pointer exits the widget.
/// released (if triggerMode is [TooltipTriggerMode.longPress]) or a tap is
/// released (if triggerMode is [TooltipTriggerMode.tap]) or mouse pointer
/// exits the widget.
///
///
/// Defaults to 1.5 seconds for long press
released or 0.1 seconds for mouse
/// Defaults to 1.5 seconds for long press
and tap released or 0.1 seconds
/// pointer exits the widget.
///
for mouse
pointer exits the widget.
final
Duration
?
showDuration
;
final
Duration
?
showDuration
;
/// The [TooltipTriggerMode] that will show the tooltip.
/// The [TooltipTriggerMode] that will show the tooltip.
...
@@ -495,7 +497,7 @@ class TooltipState extends State<Tooltip> with SingleTickerProviderStateMixin {
...
@@ -495,7 +497,7 @@ class TooltipState extends State<Tooltip> with SingleTickerProviderStateMixin {
_dismissTimer
=
null
;
_dismissTimer
=
null
;
_showTimer
?.
cancel
();
_showTimer
?.
cancel
();
_showTimer
=
null
;
_showTimer
=
null
;
if
(
_entry
!=
null
)
{
if
(
_entry
!=
null
)
{
_entry
!.
remove
();
_entry
!.
remove
();
}
}
_controller
.
reverse
();
_controller
.
reverse
();
...
@@ -674,6 +676,18 @@ class TooltipState extends State<Tooltip> with SingleTickerProviderStateMixin {
...
@@ -674,6 +676,18 @@ class TooltipState extends State<Tooltip> with SingleTickerProviderStateMixin {
widget
.
onTriggered
?.
call
();
widget
.
onTriggered
?.
call
();
}
}
void
_handleTap
()
{
_handlePress
();
// When triggerMode is not [TooltipTriggerMode.tap] the tooltip is dismissed
// by _handlePointerEvent, which listens to the global pointer events.
// When triggerMode is [TooltipTriggerMode.tap] and the Tooltip GestureDetector
// competes with other GestureDetectors, the disambiguation process will complete
// after the global pointer event is received. As we can't rely on the global
// pointer events to dismiss the Tooltip, we have to call _handleMouseExit
// to dismiss the tooltip after _showDuration expired.
_handleMouseExit
();
}
@override
@override
Widget
build
(
BuildContext
context
)
{
Widget
build
(
BuildContext
context
)
{
// If message is empty then no need to create a tooltip overlay to show
// If message is empty then no need to create a tooltip overlay to show
...
@@ -733,9 +747,8 @@ class TooltipState extends State<Tooltip> with SingleTickerProviderStateMixin {
...
@@ -733,9 +747,8 @@ class TooltipState extends State<Tooltip> with SingleTickerProviderStateMixin {
if
(
_visible
)
{
if
(
_visible
)
{
result
=
GestureDetector
(
result
=
GestureDetector
(
behavior:
HitTestBehavior
.
opaque
,
behavior:
HitTestBehavior
.
opaque
,
onLongPress:
(
_triggerMode
==
TooltipTriggerMode
.
longPress
)
?
onLongPress:
(
_triggerMode
==
TooltipTriggerMode
.
longPress
)
?
_handlePress
:
null
,
_handlePress
:
null
,
onTap:
(
_triggerMode
==
TooltipTriggerMode
.
tap
)
?
_handleTap
:
null
,
onTap:
(
_triggerMode
==
TooltipTriggerMode
.
tap
)
?
_handlePress
:
null
,
excludeFromSemantics:
true
,
excludeFromSemantics:
true
,
child:
result
,
child:
result
,
);
);
...
...
packages/flutter/test/material/tooltip_test.dart
View file @
afdfc56b
...
@@ -930,6 +930,72 @@ void main() {
...
@@ -930,6 +930,72 @@ void main() {
await
gesture
.
up
();
await
gesture
.
up
();
});
});
testWidgets
(
'Tooltip is dismissed after a long press and showDuration expired'
,
(
WidgetTester
tester
)
async
{
const
Duration
showDuration
=
Duration
(
seconds:
3
);
await
setWidgetForTooltipMode
(
tester
,
TooltipTriggerMode
.
longPress
,
showDuration:
showDuration
);
final
Finder
tooltip
=
find
.
byType
(
Tooltip
);
final
TestGesture
gesture
=
await
tester
.
startGesture
(
tester
.
getCenter
(
tooltip
));
// Long press reveals tooltip
await
tester
.
pump
(
kLongPressTimeout
);
await
tester
.
pump
(
const
Duration
(
milliseconds:
10
));
expect
(
find
.
text
(
tooltipText
),
findsOneWidget
);
await
gesture
.
up
();
// Tooltip is dismissed after showDuration expired
await
tester
.
pump
(
showDuration
);
await
tester
.
pump
(
const
Duration
(
milliseconds:
10
));
expect
(
find
.
text
(
tooltipText
),
findsNothing
);
});
testWidgets
(
'Tooltip is dismissed after a tap and showDuration expired'
,
(
WidgetTester
tester
)
async
{
const
Duration
showDuration
=
Duration
(
seconds:
3
);
await
setWidgetForTooltipMode
(
tester
,
TooltipTriggerMode
.
tap
,
showDuration:
showDuration
);
final
Finder
tooltip
=
find
.
byType
(
Tooltip
);
expect
(
find
.
text
(
tooltipText
),
findsNothing
);
await
testGestureTap
(
tester
,
tooltip
);
expect
(
find
.
text
(
tooltipText
),
findsOneWidget
);
// Tooltip is dismissed after showDuration expired
await
tester
.
pump
(
showDuration
);
await
tester
.
pump
(
const
Duration
(
milliseconds:
10
));
expect
(
find
.
text
(
tooltipText
),
findsNothing
);
});
testWidgets
(
'Tooltip is dismissed after a tap and showDuration expired when competing with a GestureDetector'
,
(
WidgetTester
tester
)
async
{
// Regression test for https://github.com/flutter/flutter/issues/98854
const
Duration
showDuration
=
Duration
(
seconds:
3
);
await
tester
.
pumpWidget
(
MaterialApp
(
home:
GestureDetector
(
onVerticalDragStart:
(
_
)
{
/* Do nothing */
},
child:
const
Tooltip
(
message:
tooltipText
,
triggerMode:
TooltipTriggerMode
.
tap
,
showDuration:
showDuration
,
child:
SizedBox
(
width:
100.0
,
height:
100.0
),
),
),
),
);
final
Finder
tooltip
=
find
.
byType
(
Tooltip
);
expect
(
find
.
text
(
tooltipText
),
findsNothing
);
await
tester
.
tap
(
tooltip
);
// Wait for GestureArena disambiguation, delay is kPressTimeout to disambiguate
// between onTap and onVerticalDragStart
await
tester
.
pump
(
kPressTimeout
);
expect
(
find
.
text
(
tooltipText
),
findsOneWidget
);
// Tooltip is dismissed after showDuration expired
await
tester
.
pump
(
showDuration
);
await
tester
.
pump
(
const
Duration
(
milliseconds:
10
));
expect
(
find
.
text
(
tooltipText
),
findsNothing
);
});
testWidgets
(
'Dispatch the mouse events before tip overlay detached'
,
(
WidgetTester
tester
)
async
{
testWidgets
(
'Dispatch the mouse events before tip overlay detached'
,
(
WidgetTester
tester
)
async
{
// Regression test for https://github.com/flutter/flutter/issues/96890
// Regression test for https://github.com/flutter/flutter/issues/96890
const
Duration
waitDuration
=
Duration
.
zero
;
const
Duration
waitDuration
=
Duration
.
zero
;
...
@@ -1840,13 +1906,19 @@ void main() {
...
@@ -1840,13 +1906,19 @@ void main() {
});
});
}
}
Future
<
void
>
setWidgetForTooltipMode
(
WidgetTester
tester
,
TooltipTriggerMode
triggerMode
,
{
TooltipTriggeredCallback
?
onTriggered
})
async
{
Future
<
void
>
setWidgetForTooltipMode
(
WidgetTester
tester
,
TooltipTriggerMode
triggerMode
,
{
Duration
?
showDuration
,
TooltipTriggeredCallback
?
onTriggered
,
})
async
{
await
tester
.
pumpWidget
(
await
tester
.
pumpWidget
(
MaterialApp
(
MaterialApp
(
home:
Tooltip
(
home:
Tooltip
(
message:
tooltipText
,
message:
tooltipText
,
triggerMode:
triggerMode
,
triggerMode:
triggerMode
,
onTriggered:
onTriggered
,
onTriggered:
onTriggered
,
showDuration:
showDuration
,
child:
const
SizedBox
(
width:
100.0
,
height:
100.0
),
child:
const
SizedBox
(
width:
100.0
,
height:
100.0
),
),
),
),
),
...
...
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