Commit c9248cd4 authored by Adam Barth's avatar Adam Barth Committed by GitHub

Tooltip can disappear too quickly (#4851)

We were stacking up two dismiss timers. Now we don't start a new timer
if we've already got one. Also, fix an animation leak caught by the
test.

Fixes #4640
parent fc711a10
...@@ -123,8 +123,12 @@ class _TooltipState extends State<Tooltip> { ...@@ -123,8 +123,12 @@ class _TooltipState extends State<Tooltip> {
} }
void ensureTooltipVisible() { void ensureTooltipVisible() {
if (_entry != null) if (_entry != null) {
_timer?.cancel();
_timer = null;
_controller.forward();
return; // Already visible. return; // Already visible.
}
RenderBox box = context.findRenderObject(); RenderBox box = context.findRenderObject();
Point target = box.localToGlobal(box.size.center(Point.origin)); Point target = box.localToGlobal(box.size.center(Point.origin));
_entry = new OverlayEntry(builder: (BuildContext context) { _entry = new OverlayEntry(builder: (BuildContext context) {
...@@ -158,7 +162,7 @@ class _TooltipState extends State<Tooltip> { ...@@ -158,7 +162,7 @@ class _TooltipState extends State<Tooltip> {
void _handlePointerEvent(PointerEvent event) { void _handlePointerEvent(PointerEvent event) {
assert(_entry != null); assert(_entry != null);
if (event is PointerUpEvent || event is PointerCancelEvent) if (event is PointerUpEvent || event is PointerCancelEvent)
_timer = new Timer(_kShowDuration, _controller.reverse); _timer ??= new Timer(_kShowDuration, _controller.reverse);
else if (event is PointerDownEvent) else if (event is PointerDownEvent)
_controller.reverse(); _controller.reverse();
} }
...@@ -174,6 +178,7 @@ class _TooltipState extends State<Tooltip> { ...@@ -174,6 +178,7 @@ class _TooltipState extends State<Tooltip> {
void dispose() { void dispose() {
if (_entry != null) if (_entry != null)
_removeEntry(); _removeEntry();
_controller.stop();
super.dispose(); super.dispose();
} }
......
...@@ -2,10 +2,11 @@ ...@@ -2,10 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';
import '../rendering/test_semantics_client.dart'; import '../rendering/test_semantics_client.dart';
...@@ -393,6 +394,43 @@ void main() { ...@@ -393,6 +394,43 @@ void main() {
expect(tip.localToGlobal(tip.size.bottomRight(Point.origin)).y, equals(320.0)); expect(tip.localToGlobal(tip.size.bottomRight(Point.origin)).y, equals(320.0));
}); });
testWidgets('Tooltip stays around', (WidgetTester tester) async {
await tester.pumpWidget(
new MaterialApp(
home: new Center(
child: new Tooltip(
message: 'TIP',
child: new Container(
width: 100.0,
height: 100.0,
decoration: new BoxDecoration(
backgroundColor: Colors.green[500]
)
)
)
)
)
);
Finder tooltip = find.byType(Tooltip);
TestGesture gesture = await tester.startGesture(tester.getCenter(tooltip));
await tester.pump(kLongPressTimeout);
await tester.pump(const Duration(milliseconds: 10));
await gesture.up();
expect(find.text('TIP'), findsOneWidget);
await tester.tap(tooltip);
await tester.pump(const Duration(milliseconds: 10));
gesture = await tester.startGesture(tester.getCenter(tooltip));
await tester.pump();
await tester.pump(const Duration(milliseconds: 300));
expect(find.text('TIP'), findsNothing);
await tester.pump(kLongPressTimeout);
expect(find.text('TIP'), findsOneWidget);
await tester.pump(kLongPressTimeout);
expect(find.text('TIP'), findsOneWidget);
gesture.up();
});
testWidgets('Does tooltip contribute semantics', (WidgetTester tester) async { testWidgets('Does tooltip contribute semantics', (WidgetTester tester) async {
TestSemanticsClient client = new TestSemanticsClient(tester.binding.pipelineOwner); TestSemanticsClient client = new TestSemanticsClient(tester.binding.pipelineOwner);
GlobalKey key = new GlobalKey(); GlobalKey key = new GlobalKey();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment