Add RawTooltip.ignorePointer (#182527)
https://github.com/flutter/flutter/issues/182468#issuecomment-3917883694
Fixes [[flutter 3.41.0] Tooltip ignorePointer property not
working](https://github.com/flutter/flutter/issues/182468)
diff --git a/packages/flutter/lib/src/material/tooltip.dart b/packages/flutter/lib/src/material/tooltip.dart
index 2c4bc16..abb85ef 100644
--- a/packages/flutter/lib/src/material/tooltip.dart
+++ b/packages/flutter/lib/src/material/tooltip.dart
@@ -531,10 +531,8 @@
semanticsTooltip: excludeFromSemantics
? null
: widget.message ?? widget.richMessage?.toPlainText() ?? '',
- tooltipBuilder: (BuildContext context, Animation<double> animation) => IgnorePointer(
- ignoring: widget.ignorePointer ?? widget.message != null,
- child: FadeTransition(opacity: animation, child: tooltipBox),
- ),
+ tooltipBuilder: (BuildContext context, Animation<double> animation) =>
+ FadeTransition(opacity: animation, child: tooltipBox),
touchDelay: widget.showDuration ?? _tooltipTheme.showDuration ?? _defaultShowDuration,
triggerMode: widget.triggerMode ?? _tooltipTheme.triggerMode ?? _defaultTriggerMode,
enableFeedback:
@@ -544,6 +542,7 @@
onTriggered: widget.onTriggered,
dismissDelay: widget.exitDuration ?? _tooltipTheme.exitDuration ?? _defaultExitDuration,
positionDelegate: _getDefaultPositionDelegate,
+ ignorePointer: widget.ignorePointer ?? widget.message != null,
child: effectiveChild,
);
}
diff --git a/packages/flutter/lib/src/widgets/raw_tooltip.dart b/packages/flutter/lib/src/widgets/raw_tooltip.dart
index 90abd38..7566dfd 100644
--- a/packages/flutter/lib/src/widgets/raw_tooltip.dart
+++ b/packages/flutter/lib/src/widgets/raw_tooltip.dart
@@ -252,6 +252,7 @@
this.onTriggered,
this.animationStyle = _kDefaultAnimationStyle,
this.positionDelegate,
+ this.ignorePointer = false,
required this.child,
});
@@ -453,6 +454,16 @@
/// {@endtemplate}
final TooltipPositionDelegate? positionDelegate;
+ /// Whether the tooltip should be invisible to hit testing.
+ ///
+ /// Defaults to false.
+ ///
+ /// See also:
+ ///
+ /// * [IgnorePointer], for more information about how pointer events are
+ /// handled or ignored.
+ final bool ignorePointer;
+
/// The widget below this widget in the tree.
///
/// The widget returned in [tooltipBuilder] will be shown when the user hovers
@@ -798,10 +809,13 @@
);
// Keep the tooltip visible while the overlay child is hovered.
- final Widget tooltip = _ExclusiveMouseRegion(
- onEnter: _handleMouseEnter,
- onExit: _handleMouseExit,
- child: widget.tooltipBuilder(context, _overlayAnimation),
+ final Widget tooltip = IgnorePointer(
+ ignoring: widget.ignorePointer,
+ child: _ExclusiveMouseRegion(
+ onEnter: _handleMouseEnter,
+ onExit: _handleMouseExit,
+ child: widget.tooltipBuilder(context, _overlayAnimation),
+ ),
);
final Widget overlayChild = Positioned.fill(
diff --git a/packages/flutter/test/material/tooltip_test.dart b/packages/flutter/test/material/tooltip_test.dart
index 273a7fa..e3162fd 100644
--- a/packages/flutter/test/material/tooltip_test.dart
+++ b/packages/flutter/test/material/tooltip_test.dart
@@ -2055,6 +2055,39 @@
expect(tester.getSize(find.byType(Tooltip)), Size.zero);
expect(find.text('X'), findsOne);
});
+
+ testWidgets('Tooltip should disappear even if mouse is hovering over the tooltip overlay', (
+ WidgetTester tester,
+ ) async {
+ await tester.pumpWidget(
+ const MaterialApp(
+ home: Center(
+ child: Tooltip(message: tooltipText, child: Text('Hover me')),
+ ),
+ ),
+ );
+
+ // Hover over the target widget.
+ final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse);
+ await gesture.addPointer(location: Offset.zero);
+ addTearDown(gesture.removePointer);
+
+ final Finder targetFinder = find.text('Hover me');
+ await gesture.moveTo(tester.getCenter(targetFinder));
+ await tester.pump();
+
+ // Wait for the tooltip to actually appear.
+ await tester.pump(const Duration(milliseconds: 100));
+ expect(find.text(tooltipText), findsOneWidget);
+
+ // Move the mouse to the tooltip overlay.
+ final Finder tooltipOverlayFinder = find.text(tooltipText);
+ await gesture.moveTo(tester.getCenter(tooltipOverlayFinder));
+ await tester.pumpAndSettle();
+
+ // Verify the tooltip overlay is no longer displayed.
+ expect(find.text(tooltipText), findsNothing);
+ });
}
Future<void> _testGestureTap(WidgetTester tester, Finder tooltip) async {
diff --git a/packages/flutter/test/widgets/raw_tooltip_test.dart b/packages/flutter/test/widgets/raw_tooltip_test.dart
index 2bd2b66..3104035 100644
--- a/packages/flutter/test/widgets/raw_tooltip_test.dart
+++ b/packages/flutter/test/widgets/raw_tooltip_test.dart
@@ -12,6 +12,7 @@
import 'package:flutter_test/flutter_test.dart';
import '../widgets/feedback_tester.dart';
import '../widgets/semantics_tester.dart';
+import 'widgets_app_tester.dart';
const String tooltipText = 'TIP';
@@ -2740,6 +2741,45 @@
expect(tooltipPosition.dx, closeTo(targetCenter.dx + 25, 5.0));
expect(tooltipPosition.dy, closeTo(targetCenter.dy - 25 - 14, 5.0));
});
+
+ testWidgets('RawTooltip ignores pointer events when ignorePointer is true', (
+ WidgetTester tester,
+ ) async {
+ await tester.pumpWidget(
+ TestWidgetsApp(
+ home: Center(
+ child: RawTooltip(
+ semanticsTooltip: tooltipText,
+ tooltipBuilder: (BuildContext context, Animation<double> animation) =>
+ const Placeholder(child: Text(tooltipText)),
+ ignorePointer: true,
+ child: const Text('Hover me'),
+ ),
+ ),
+ ),
+ );
+
+ // Hover over the target widget.
+ final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse);
+ await gesture.addPointer(location: Offset.zero);
+ addTearDown(gesture.removePointer);
+
+ final Finder targetFinder = find.text('Hover me');
+ await gesture.moveTo(tester.getCenter(targetFinder));
+ await tester.pump();
+
+ // Wait for the tooltip to actually appear.
+ await tester.pump(const Duration(milliseconds: 100));
+ expect(find.text(tooltipText), findsOneWidget);
+
+ // Move the mouse to the tooltip overlay.
+ final Finder tooltipOverlayFinder = find.text(tooltipText);
+ await gesture.moveTo(tester.getCenter(tooltipOverlayFinder));
+ await tester.pumpAndSettle();
+
+ // Verify the tooltip overlay is no longer displayed.
+ expect(find.text(tooltipText), findsNothing);
+ });
}
Future<void> setWidgetForTooltipMode(