Unverified Commit 7b6af52c authored by Hans Muller's avatar Hans Muller Committed by GitHub

Improve TextField splash management: cancel() ... confirm() (#14130)

parent b94f757d
......@@ -190,7 +190,10 @@ class InkRipple extends InteractiveInkFeature {
_radiusController
..duration = _kRadiusDuration
..forward();
_fadeOutController.forward();
// This confirm may have been preceeded by a cancel.
_fadeInController.forward();
_fadeOutController
..animateTo(1.0, duration: _kFadeOutDuration);
}
@override
......
......@@ -414,7 +414,6 @@ class _TextFieldState extends State<TextField> with AutomaticKeepAliveClientMixi
void _cancelCurrentSplash() {
_currentSplash?.cancel();
_currentSplash = null;
}
@override
......
......@@ -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:flutter/gestures.dart' show kPressTimeout;
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/rendering.dart';
......@@ -176,7 +177,13 @@ void main() {
// Pointer is dragged below the textfield, splash is canceled.
final TestGesture gesture1 = await tester.startGesture(tester.getCenter(find.text('label1')));
await tester.pumpAndSettle();
// Splashes start on tapDown.
// If the timeout is less than kPressTimout the recognizer will just trigger
// the onTapCancel callback. If the timeout is greater or equal to kPressTimout
// and less than kLongPressTimeout then onTapDown, onCancel will be called.
await tester.pump(kPressTimeout);
await gesture1.moveTo(const Offset(400.0, 300.0));
await gesture1.up();
expect(confirmCount, 0);
......@@ -184,11 +191,10 @@ void main() {
// Pointer is dragged upwards causing a scroll, splash is canceled.
final TestGesture gesture2 = await tester.startGesture(tester.getCenter(find.text('label2')));
await tester.pumpAndSettle();
await gesture2.moveBy(const Offset(0.0, -200.0), timeStamp: const Duration(milliseconds: 32));
await tester.pump(kPressTimeout);
await gesture2.moveBy(const Offset(0.0, -200.0));
await gesture2.up();
expect(confirmCount, 0);
expect(cancelCount, 2);
});
}
......@@ -251,4 +251,67 @@ void main() {
expect(renderObj1, same(renderObj2));
expect(actualCallback1, same(actualCallback2)); // Should be cached.
});
testWidgets('Tap down occurs after kPressTimeout', (WidgetTester tester) async {
int tapDown = 0;
int tap = 0;
int tapCancel = 0;
int longPress = 0;
await tester.pumpWidget(
new Container(
alignment: Alignment.topLeft,
child: new Container(
alignment: Alignment.center,
height: 100.0,
color: const Color(0xFF00FF00),
child: new GestureDetector(
onTapDown: (TapDownDetails details) {
tapDown += 1;
},
onTap: () {
tap += 1;
},
onTapCancel: () {
tapCancel += 1;
},
onLongPress: () {
longPress += 1;
},
),
),
),
);
// Pointer is dragged from the center of the 800x100 gesture detector
// to a point (400,300) below it. This always causes onTapCancel to be
// called; onTap should never be called.
Future<Null> dragOut(Duration timeout) async {
final TestGesture gesture = await tester.startGesture(const Offset(400.0, 50.0));
// If the timeout is less than kPressTimout the recognizer will just trigger
// the onTapCancel callback. If the timeout is greater than kLongPressTimeout
// then onTapDown, onLongPress, and onCancel will be called.
await tester.pump(timeout);
await gesture.moveTo(const Offset(400.0, 300.0));
await gesture.up();
}
await dragOut(kPressTimeout * 0.5); // generates tapCancel
expect(tapDown, 0);
expect(tapCancel, 1);
expect(tap, 0);
expect(longPress, 0);
await dragOut(kPressTimeout); // generates tapDown, tapCancel
expect(tapDown, 1);
expect(tapCancel, 2);
expect(tap, 0);
expect(longPress, 0);
await dragOut(kLongPressTimeout); // generates tapDown, longPress, tapCancel
expect(tapDown, 2);
expect(tapCancel, 3);
expect(tap, 0);
expect(longPress, 1);
});
}
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