670 lines
27 KiB
Dart
670 lines
27 KiB
Dart
// Copyright 2014 The Flutter Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
import 'dart:math' as math;
|
|
|
|
import 'package:flutter/gestures.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
|
|
import '../foundation/leak_tracking.dart';
|
|
|
|
void main() {
|
|
group('Horizontal', () {
|
|
testWidgets('gets local coordinates', (WidgetTester tester) async {
|
|
int dragCancelCount = 0;
|
|
final List<DragDownDetails> downDetails = <DragDownDetails>[];
|
|
final List<DragEndDetails> endDetails = <DragEndDetails>[];
|
|
final List<DragStartDetails> startDetails = <DragStartDetails>[];
|
|
final List<DragUpdateDetails> updateDetails = <DragUpdateDetails>[];
|
|
|
|
final Key redContainer = UniqueKey();
|
|
await tester.pumpWidget(
|
|
Center(
|
|
child: GestureDetector(
|
|
onHorizontalDragCancel: () {
|
|
dragCancelCount++;
|
|
},
|
|
onHorizontalDragDown: (DragDownDetails details) {
|
|
downDetails.add(details);
|
|
},
|
|
onHorizontalDragEnd: (DragEndDetails details) {
|
|
endDetails.add(details);
|
|
},
|
|
onHorizontalDragStart: (DragStartDetails details) {
|
|
startDetails.add(details);
|
|
},
|
|
onHorizontalDragUpdate: (DragUpdateDetails details) {
|
|
updateDetails.add(details);
|
|
},
|
|
child: Container(
|
|
key: redContainer,
|
|
width: 100,
|
|
height: 150,
|
|
color: Colors.red,
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
await tester.drag(find.byKey(redContainer), const Offset(100, 0));
|
|
expect(dragCancelCount, 0);
|
|
expect(downDetails.single.localPosition, const Offset(50, 75));
|
|
expect(downDetails.single.globalPosition, const Offset(400, 300));
|
|
expect(endDetails, hasLength(1));
|
|
expect(startDetails.single.localPosition, const Offset(50, 75));
|
|
expect(startDetails.single.globalPosition, const Offset(400, 300));
|
|
expect(updateDetails.last.localPosition, const Offset(50 + 100.0, 75));
|
|
expect(updateDetails.last.globalPosition, const Offset(400 + 100.0, 300));
|
|
expect(
|
|
updateDetails.fold(Offset.zero, (Offset offset, DragUpdateDetails details) => offset + details.delta),
|
|
const Offset(100, 0),
|
|
);
|
|
expect(
|
|
updateDetails.fold(0.0, (double offset, DragUpdateDetails details) => offset + (details.primaryDelta ?? 0)),
|
|
100.0,
|
|
);
|
|
});
|
|
|
|
testWidgetsWithLeakTracking('kTouchSlop is evaluated in the global coordinate space when scaled up', (WidgetTester tester) async {
|
|
int dragCancelCount = 0;
|
|
final List<DragDownDetails> downDetails = <DragDownDetails>[];
|
|
final List<DragEndDetails> endDetails = <DragEndDetails>[];
|
|
final List<DragStartDetails> startDetails = <DragStartDetails>[];
|
|
final List<DragUpdateDetails> updateDetails = <DragUpdateDetails>[];
|
|
|
|
final Key redContainer = UniqueKey();
|
|
await tester.pumpWidget(
|
|
Center(
|
|
child: Transform.scale(
|
|
scale: 2.0,
|
|
child: GestureDetector(
|
|
onHorizontalDragCancel: () {
|
|
dragCancelCount++;
|
|
},
|
|
onHorizontalDragDown: (DragDownDetails details) {
|
|
downDetails.add(details);
|
|
},
|
|
onHorizontalDragEnd: (DragEndDetails details) {
|
|
endDetails.add(details);
|
|
},
|
|
onHorizontalDragStart: (DragStartDetails details) {
|
|
startDetails.add(details);
|
|
},
|
|
onHorizontalDragUpdate: (DragUpdateDetails details) {
|
|
updateDetails.add(details);
|
|
},
|
|
onTap: () {
|
|
// Competing gesture detector.
|
|
},
|
|
child: Container(
|
|
key: redContainer,
|
|
width: 100,
|
|
height: 150,
|
|
color: Colors.red,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
// Move just above kTouchSlop should recognize drag.
|
|
await tester.drag(find.byKey(redContainer), const Offset(kTouchSlop + 1, 0));
|
|
|
|
expect(dragCancelCount, 0);
|
|
expect(downDetails.single.localPosition, const Offset(50, 75));
|
|
expect(downDetails.single.globalPosition, const Offset(400, 300));
|
|
expect(endDetails, hasLength(1));
|
|
expect(startDetails.single.localPosition, const Offset(50 + (kTouchSlop + 1) / 2, 75));
|
|
expect(startDetails.single.globalPosition, const Offset(400 + (kTouchSlop + 1), 300));
|
|
expect(updateDetails, isEmpty);
|
|
|
|
dragCancelCount = 0;
|
|
downDetails.clear();
|
|
endDetails.clear();
|
|
startDetails.clear();
|
|
updateDetails.clear();
|
|
|
|
// Move just below kTouchSlop does not recognize drag.
|
|
await tester.drag(find.byKey(redContainer), const Offset(kTouchSlop - 1, 0));
|
|
expect(dragCancelCount, 1);
|
|
expect(downDetails.single.localPosition, const Offset(50, 75));
|
|
expect(downDetails.single.globalPosition, const Offset(400, 300));
|
|
expect(endDetails, isEmpty);
|
|
expect(startDetails, isEmpty);
|
|
expect(updateDetails, isEmpty);
|
|
|
|
dragCancelCount = 0;
|
|
downDetails.clear();
|
|
endDetails.clear();
|
|
startDetails.clear();
|
|
updateDetails.clear();
|
|
|
|
// Move in two separate movements
|
|
final TestGesture gesture = await tester.startGesture(tester.getCenter(find.byKey(redContainer)));
|
|
await gesture.moveBy(const Offset(kTouchSlop + 1, 30));
|
|
await gesture.moveBy(const Offset(100, 10));
|
|
await gesture.up();
|
|
|
|
expect(dragCancelCount, 0);
|
|
expect(downDetails.single.localPosition, const Offset(50, 75));
|
|
expect(downDetails.single.globalPosition, const Offset(400, 300));
|
|
expect(endDetails, hasLength(1));
|
|
expect(startDetails.single.localPosition, const Offset(50 + (kTouchSlop + 1) / 2, 75.0 + 30.0 / 2));
|
|
expect(startDetails.single.globalPosition, const Offset(400 + (kTouchSlop + 1), 300 + 30.0));
|
|
expect(updateDetails.single.localPosition, startDetails.single.localPosition + const Offset(100.0 / 2, 10 / 2));
|
|
expect(updateDetails.single.globalPosition, startDetails.single.globalPosition + const Offset(100.0, 10.0));
|
|
expect(updateDetails.single.delta, const Offset(100.0 / 2, 0.0));
|
|
expect(updateDetails.single.primaryDelta, 100.0 / 2);
|
|
|
|
dragCancelCount = 0;
|
|
downDetails.clear();
|
|
endDetails.clear();
|
|
startDetails.clear();
|
|
updateDetails.clear();
|
|
});
|
|
|
|
testWidgetsWithLeakTracking('kTouchSlop is evaluated in the global coordinate space when scaled down', (WidgetTester tester) async {
|
|
int dragCancelCount = 0;
|
|
final List<DragDownDetails> downDetails = <DragDownDetails>[];
|
|
final List<DragEndDetails> endDetails = <DragEndDetails>[];
|
|
final List<DragStartDetails> startDetails = <DragStartDetails>[];
|
|
final List<DragUpdateDetails> updateDetails = <DragUpdateDetails>[];
|
|
|
|
final Key redContainer = UniqueKey();
|
|
await tester.pumpWidget(
|
|
Center(
|
|
child: Transform.scale(
|
|
scale: 0.5,
|
|
child: GestureDetector(
|
|
onHorizontalDragCancel: () {
|
|
dragCancelCount++;
|
|
},
|
|
onHorizontalDragDown: (DragDownDetails details) {
|
|
downDetails.add(details);
|
|
},
|
|
onHorizontalDragEnd: (DragEndDetails details) {
|
|
endDetails.add(details);
|
|
},
|
|
onHorizontalDragStart: (DragStartDetails details) {
|
|
startDetails.add(details);
|
|
},
|
|
onHorizontalDragUpdate: (DragUpdateDetails details) {
|
|
updateDetails.add(details);
|
|
},
|
|
onTap: () {
|
|
// Competing gesture detector.
|
|
},
|
|
child: Container(
|
|
key: redContainer,
|
|
width: 100,
|
|
height: 150,
|
|
color: Colors.red,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
// Move just above kTouchSlop should recognize drag.
|
|
await tester.drag(find.byKey(redContainer), const Offset(kTouchSlop + 1, 0));
|
|
|
|
expect(dragCancelCount, 0);
|
|
expect(downDetails.single.localPosition, const Offset(50, 75));
|
|
expect(downDetails.single.globalPosition, const Offset(400, 300));
|
|
expect(endDetails, hasLength(1));
|
|
expect(startDetails.single.localPosition, const Offset(50 + (kTouchSlop + 1) * 2, 75));
|
|
expect(startDetails.single.globalPosition, const Offset(400 + (kTouchSlop + 1), 300));
|
|
expect(updateDetails, isEmpty);
|
|
|
|
dragCancelCount = 0;
|
|
downDetails.clear();
|
|
endDetails.clear();
|
|
startDetails.clear();
|
|
updateDetails.clear();
|
|
|
|
// Move just below kTouchSlop does not recognize drag.
|
|
await tester.drag(find.byKey(redContainer), const Offset(kTouchSlop - 1, 0));
|
|
expect(dragCancelCount, 1);
|
|
expect(downDetails.single.localPosition, const Offset(50, 75));
|
|
expect(downDetails.single.globalPosition, const Offset(400, 300));
|
|
expect(endDetails, isEmpty);
|
|
expect(startDetails, isEmpty);
|
|
expect(updateDetails, isEmpty);
|
|
|
|
dragCancelCount = 0;
|
|
downDetails.clear();
|
|
endDetails.clear();
|
|
startDetails.clear();
|
|
updateDetails.clear();
|
|
|
|
// Move in two separate movements
|
|
final TestGesture gesture = await tester.startGesture(tester.getCenter(find.byKey(redContainer)));
|
|
await gesture.moveBy(const Offset(kTouchSlop + 1, 30));
|
|
await gesture.moveBy(const Offset(100, 10));
|
|
await gesture.up();
|
|
|
|
expect(dragCancelCount, 0);
|
|
expect(downDetails.single.localPosition, const Offset(50, 75));
|
|
expect(downDetails.single.globalPosition, const Offset(400, 300));
|
|
expect(endDetails, hasLength(1));
|
|
expect(startDetails.single.localPosition, const Offset(50 + (kTouchSlop + 1) * 2, 75.0 + 30.0 * 2));
|
|
expect(startDetails.single.globalPosition, const Offset(400 + (kTouchSlop + 1), 300 + 30.0));
|
|
expect(updateDetails.single.localPosition, startDetails.single.localPosition + const Offset(100.0 * 2, 10.0 * 2.0));
|
|
expect(updateDetails.single.globalPosition, startDetails.single.globalPosition + const Offset(100.0, 10.0));
|
|
expect(updateDetails.single.delta, const Offset(100.0 * 2.0, 0.0));
|
|
expect(updateDetails.single.primaryDelta, 100.0 * 2);
|
|
|
|
dragCancelCount = 0;
|
|
downDetails.clear();
|
|
endDetails.clear();
|
|
startDetails.clear();
|
|
updateDetails.clear();
|
|
});
|
|
|
|
testWidgetsWithLeakTracking('kTouchSlop is evaluated in the global coordinate space when rotated 45 degrees', (WidgetTester tester) async {
|
|
int dragCancelCount = 0;
|
|
final List<DragDownDetails> downDetails = <DragDownDetails>[];
|
|
final List<DragEndDetails> endDetails = <DragEndDetails>[];
|
|
final List<DragStartDetails> startDetails = <DragStartDetails>[];
|
|
final List<DragUpdateDetails> updateDetails = <DragUpdateDetails>[];
|
|
|
|
final Key redContainer = UniqueKey();
|
|
await tester.pumpWidget(
|
|
Center(
|
|
child: Transform.rotate(
|
|
angle: math.pi / 4,
|
|
child: GestureDetector(
|
|
onHorizontalDragCancel: () {
|
|
dragCancelCount++;
|
|
},
|
|
onHorizontalDragDown: (DragDownDetails details) {
|
|
downDetails.add(details);
|
|
},
|
|
onHorizontalDragEnd: (DragEndDetails details) {
|
|
endDetails.add(details);
|
|
},
|
|
onHorizontalDragStart: (DragStartDetails details) {
|
|
startDetails.add(details);
|
|
},
|
|
onHorizontalDragUpdate: (DragUpdateDetails details) {
|
|
updateDetails.add(details);
|
|
},
|
|
onTap: () {
|
|
// Competing gesture detector.
|
|
},
|
|
child: Container(
|
|
key: redContainer,
|
|
width: 100,
|
|
height: 150,
|
|
color: Colors.red,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
// Move just below kTouchSlop should not recognize drag.
|
|
const Offset moveBy1 = Offset(kTouchSlop/ 2, kTouchSlop / 2);
|
|
expect(moveBy1.distance, lessThan(kTouchSlop));
|
|
await tester.drag(find.byKey(redContainer), moveBy1);
|
|
expect(dragCancelCount, 1);
|
|
expect(downDetails.single.localPosition, within(distance: 0.0001, from: const Offset(50, 75)));
|
|
expect(downDetails.single.globalPosition, within(distance: 0.0001, from: const Offset(400, 300)));
|
|
expect(endDetails, isEmpty);
|
|
expect(startDetails, isEmpty);
|
|
expect(updateDetails, isEmpty);
|
|
|
|
dragCancelCount = 0;
|
|
downDetails.clear();
|
|
endDetails.clear();
|
|
startDetails.clear();
|
|
updateDetails.clear();
|
|
|
|
// Move above kTouchSlop recognizes drag.
|
|
final TestGesture gesture = await tester.startGesture(tester.getCenter(find.byKey(redContainer)));
|
|
await gesture.moveBy(const Offset(kTouchSlop, kTouchSlop));
|
|
await gesture.moveBy(const Offset(3, 4));
|
|
await gesture.up();
|
|
|
|
expect(dragCancelCount, 0);
|
|
expect(downDetails.single.localPosition, within(distance: 0.0001, from: const Offset(50, 75)));
|
|
expect(downDetails.single.globalPosition, within(distance: 0.0001, from: const Offset(400, 300)));
|
|
expect(endDetails, hasLength(1));
|
|
expect(startDetails, hasLength(1));
|
|
expect(updateDetails.single.globalPosition, within(distance: 0.0001, from: const Offset(400 + kTouchSlop + 3, 300 + kTouchSlop + 4)));
|
|
expect(updateDetails.single.delta, within(distance: 0.1, from: const Offset(5, 0.0))); // sqrt(3^2 + 4^2)
|
|
expect(updateDetails.single.primaryDelta, within<double>(distance: 0.1, from: 5.0)); // sqrt(3^2 + 4^2)
|
|
});
|
|
});
|
|
|
|
group('Vertical', () {
|
|
testWidgetsWithLeakTracking('gets local coordinates', (WidgetTester tester) async {
|
|
int dragCancelCount = 0;
|
|
final List<DragDownDetails> downDetails = <DragDownDetails>[];
|
|
final List<DragEndDetails> endDetails = <DragEndDetails>[];
|
|
final List<DragStartDetails> startDetails = <DragStartDetails>[];
|
|
final List<DragUpdateDetails> updateDetails = <DragUpdateDetails>[];
|
|
|
|
final Key redContainer = UniqueKey();
|
|
await tester.pumpWidget(
|
|
Center(
|
|
child: GestureDetector(
|
|
onVerticalDragCancel: () {
|
|
dragCancelCount++;
|
|
},
|
|
onVerticalDragDown: (DragDownDetails details) {
|
|
downDetails.add(details);
|
|
},
|
|
onVerticalDragEnd: (DragEndDetails details) {
|
|
endDetails.add(details);
|
|
},
|
|
onVerticalDragStart: (DragStartDetails details) {
|
|
startDetails.add(details);
|
|
},
|
|
onVerticalDragUpdate: (DragUpdateDetails details) {
|
|
updateDetails.add(details);
|
|
},
|
|
child: Container(
|
|
key: redContainer,
|
|
width: 100,
|
|
height: 150,
|
|
color: Colors.red,
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
await tester.drag(find.byKey(redContainer), const Offset(0, 100));
|
|
expect(dragCancelCount, 0);
|
|
expect(downDetails.single.localPosition, const Offset(50, 75));
|
|
expect(downDetails.single.globalPosition, const Offset(400, 300));
|
|
expect(endDetails, hasLength(1));
|
|
expect(startDetails.single.localPosition, const Offset(50, 75));
|
|
expect(startDetails.single.globalPosition, const Offset(400, 300));
|
|
expect(updateDetails.last.localPosition, const Offset(50, 75 + 100.0));
|
|
expect(updateDetails.last.globalPosition, const Offset(400, 300 + 100.0));
|
|
expect(
|
|
updateDetails.fold(Offset.zero, (Offset offset, DragUpdateDetails details) => offset + details.delta),
|
|
const Offset(0, 100),
|
|
);
|
|
expect(
|
|
updateDetails.fold(0.0, (double offset, DragUpdateDetails details) => offset + (details.primaryDelta ?? 0)),
|
|
100.0,
|
|
);
|
|
});
|
|
|
|
testWidgetsWithLeakTracking('kTouchSlop is evaluated in the global coordinate space when scaled up', (WidgetTester tester) async {
|
|
int dragCancelCount = 0;
|
|
final List<DragDownDetails> downDetails = <DragDownDetails>[];
|
|
final List<DragEndDetails> endDetails = <DragEndDetails>[];
|
|
final List<DragStartDetails> startDetails = <DragStartDetails>[];
|
|
final List<DragUpdateDetails> updateDetails = <DragUpdateDetails>[];
|
|
|
|
final Key redContainer = UniqueKey();
|
|
await tester.pumpWidget(
|
|
Center(
|
|
child: Transform.scale(
|
|
scale: 2.0,
|
|
child: GestureDetector(
|
|
onVerticalDragCancel: () {
|
|
dragCancelCount++;
|
|
},
|
|
onVerticalDragDown: (DragDownDetails details) {
|
|
downDetails.add(details);
|
|
},
|
|
onVerticalDragEnd: (DragEndDetails details) {
|
|
endDetails.add(details);
|
|
},
|
|
onVerticalDragStart: (DragStartDetails details) {
|
|
startDetails.add(details);
|
|
},
|
|
onVerticalDragUpdate: (DragUpdateDetails details) {
|
|
updateDetails.add(details);
|
|
},
|
|
onTap: () {
|
|
// Competing gesture detector.
|
|
},
|
|
child: Container(
|
|
key: redContainer,
|
|
width: 100,
|
|
height: 150,
|
|
color: Colors.red,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
// Move just above kTouchSlop should recognize drag.
|
|
await tester.drag(find.byKey(redContainer), const Offset(0, kTouchSlop + 1));
|
|
|
|
expect(dragCancelCount, 0);
|
|
expect(downDetails.single.localPosition, const Offset(50, 75));
|
|
expect(downDetails.single.globalPosition, const Offset(400, 300));
|
|
expect(endDetails, hasLength(1));
|
|
expect(startDetails.single.localPosition, const Offset(50, 75 + (kTouchSlop + 1) / 2));
|
|
expect(startDetails.single.globalPosition, const Offset(400, 300 + (kTouchSlop + 1)));
|
|
expect(updateDetails, isEmpty);
|
|
|
|
dragCancelCount = 0;
|
|
downDetails.clear();
|
|
endDetails.clear();
|
|
startDetails.clear();
|
|
updateDetails.clear();
|
|
|
|
// Move just below kTouchSlop does not recognize drag.
|
|
await tester.drag(find.byKey(redContainer), const Offset(0, kTouchSlop - 1));
|
|
expect(dragCancelCount, 1);
|
|
expect(downDetails.single.localPosition, const Offset(50, 75));
|
|
expect(downDetails.single.globalPosition, const Offset(400, 300));
|
|
expect(endDetails, isEmpty);
|
|
expect(startDetails, isEmpty);
|
|
expect(updateDetails, isEmpty);
|
|
|
|
dragCancelCount = 0;
|
|
downDetails.clear();
|
|
endDetails.clear();
|
|
startDetails.clear();
|
|
updateDetails.clear();
|
|
|
|
// Move in two separate movements
|
|
final TestGesture gesture = await tester.startGesture(tester.getCenter(find.byKey(redContainer)));
|
|
await gesture.moveBy(const Offset(30, kTouchSlop + 1));
|
|
await gesture.moveBy(const Offset(10, 100));
|
|
await gesture.up();
|
|
|
|
expect(dragCancelCount, 0);
|
|
expect(downDetails.single.localPosition, const Offset(50, 75));
|
|
expect(downDetails.single.globalPosition, const Offset(400, 300));
|
|
expect(endDetails, hasLength(1));
|
|
expect(startDetails.single.localPosition, const Offset(50 + 30.0 / 2, 75.0 + (kTouchSlop + 1) / 2));
|
|
expect(startDetails.single.globalPosition, const Offset(400 + 30.0, 300 + (kTouchSlop + 1)));
|
|
expect(updateDetails.single.localPosition, startDetails.single.localPosition + const Offset(10.0 / 2, 100.0 / 2));
|
|
expect(updateDetails.single.globalPosition, startDetails.single.globalPosition + const Offset(10.0, 100.0));
|
|
expect(updateDetails.single.delta, const Offset(0.0, 100.0 / 2));
|
|
expect(updateDetails.single.primaryDelta, 100.0 / 2);
|
|
|
|
dragCancelCount = 0;
|
|
downDetails.clear();
|
|
endDetails.clear();
|
|
startDetails.clear();
|
|
updateDetails.clear();
|
|
});
|
|
|
|
testWidgetsWithLeakTracking('kTouchSlop is evaluated in the global coordinate space when scaled down', (WidgetTester tester) async {
|
|
int dragCancelCount = 0;
|
|
final List<DragDownDetails> downDetails = <DragDownDetails>[];
|
|
final List<DragEndDetails> endDetails = <DragEndDetails>[];
|
|
final List<DragStartDetails> startDetails = <DragStartDetails>[];
|
|
final List<DragUpdateDetails> updateDetails = <DragUpdateDetails>[];
|
|
|
|
final Key redContainer = UniqueKey();
|
|
await tester.pumpWidget(
|
|
Center(
|
|
child: Transform.scale(
|
|
scale: 0.5,
|
|
child: GestureDetector(
|
|
onVerticalDragCancel: () {
|
|
dragCancelCount++;
|
|
},
|
|
onVerticalDragDown: (DragDownDetails details) {
|
|
downDetails.add(details);
|
|
},
|
|
onVerticalDragEnd: (DragEndDetails details) {
|
|
endDetails.add(details);
|
|
},
|
|
onVerticalDragStart: (DragStartDetails details) {
|
|
startDetails.add(details);
|
|
},
|
|
onVerticalDragUpdate: (DragUpdateDetails details) {
|
|
updateDetails.add(details);
|
|
},
|
|
onTap: () {
|
|
// Competing gesture detector.
|
|
},
|
|
child: Container(
|
|
key: redContainer,
|
|
width: 100,
|
|
height: 150,
|
|
color: Colors.red,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
// Move just above kTouchSlop should recognize drag.
|
|
await tester.drag(find.byKey(redContainer), const Offset(0, kTouchSlop + 1));
|
|
|
|
expect(dragCancelCount, 0);
|
|
expect(downDetails.single.localPosition, const Offset(50, 75));
|
|
expect(downDetails.single.globalPosition, const Offset(400, 300));
|
|
expect(endDetails, hasLength(1));
|
|
expect(startDetails.single.localPosition, const Offset(50, 75 + (kTouchSlop + 1) * 2));
|
|
expect(startDetails.single.globalPosition, const Offset(400, 300 + (kTouchSlop + 1)));
|
|
expect(updateDetails, isEmpty);
|
|
|
|
dragCancelCount = 0;
|
|
downDetails.clear();
|
|
endDetails.clear();
|
|
startDetails.clear();
|
|
updateDetails.clear();
|
|
|
|
// Move just below kTouchSlop does not recognize drag.
|
|
await tester.drag(find.byKey(redContainer), const Offset(0, kTouchSlop - 1));
|
|
expect(dragCancelCount, 1);
|
|
expect(downDetails.single.localPosition, const Offset(50, 75));
|
|
expect(downDetails.single.globalPosition, const Offset(400, 300));
|
|
expect(endDetails, isEmpty);
|
|
expect(startDetails, isEmpty);
|
|
expect(updateDetails, isEmpty);
|
|
|
|
dragCancelCount = 0;
|
|
downDetails.clear();
|
|
endDetails.clear();
|
|
startDetails.clear();
|
|
updateDetails.clear();
|
|
|
|
// Move in two separate movements
|
|
final TestGesture gesture = await tester.startGesture(tester.getCenter(find.byKey(redContainer)));
|
|
await gesture.moveBy(const Offset(30, kTouchSlop + 1));
|
|
await gesture.moveBy(const Offset(10, 100));
|
|
await gesture.up();
|
|
|
|
expect(dragCancelCount, 0);
|
|
expect(downDetails.single.localPosition, const Offset(50, 75));
|
|
expect(downDetails.single.globalPosition, const Offset(400, 300));
|
|
expect(endDetails, hasLength(1));
|
|
expect(startDetails.single.localPosition, const Offset(50 + 30.0 * 2, 75.0 + (kTouchSlop + 1) * 2));
|
|
expect(startDetails.single.globalPosition, const Offset(400 + 30.0, 300 + (kTouchSlop + 1)));
|
|
expect(updateDetails.single.localPosition, startDetails.single.localPosition + const Offset(10.0 * 2, 100.0 * 2.0));
|
|
expect(updateDetails.single.globalPosition, startDetails.single.globalPosition + const Offset(10.0, 100.0));
|
|
expect(updateDetails.single.delta, const Offset(0.0, 100.0 * 2.0));
|
|
expect(updateDetails.single.primaryDelta, 100.0 * 2);
|
|
|
|
dragCancelCount = 0;
|
|
downDetails.clear();
|
|
endDetails.clear();
|
|
startDetails.clear();
|
|
updateDetails.clear();
|
|
});
|
|
|
|
testWidgetsWithLeakTracking('kTouchSlop is evaluated in the global coordinate space when rotated 45 degrees', (WidgetTester tester) async {
|
|
int dragCancelCount = 0;
|
|
final List<DragDownDetails> downDetails = <DragDownDetails>[];
|
|
final List<DragEndDetails> endDetails = <DragEndDetails>[];
|
|
final List<DragStartDetails> startDetails = <DragStartDetails>[];
|
|
final List<DragUpdateDetails> updateDetails = <DragUpdateDetails>[];
|
|
|
|
final Key redContainer = UniqueKey();
|
|
await tester.pumpWidget(
|
|
Center(
|
|
child: Transform.rotate(
|
|
angle: math.pi / 4,
|
|
child: GestureDetector(
|
|
onVerticalDragCancel: () {
|
|
dragCancelCount++;
|
|
},
|
|
onVerticalDragDown: (DragDownDetails details) {
|
|
downDetails.add(details);
|
|
},
|
|
onVerticalDragEnd: (DragEndDetails details) {
|
|
endDetails.add(details);
|
|
},
|
|
onVerticalDragStart: (DragStartDetails details) {
|
|
startDetails.add(details);
|
|
},
|
|
onVerticalDragUpdate: (DragUpdateDetails details) {
|
|
updateDetails.add(details);
|
|
},
|
|
onTap: () {
|
|
// Competing gesture detector.
|
|
},
|
|
child: Container(
|
|
key: redContainer,
|
|
width: 100,
|
|
height: 150,
|
|
color: Colors.red,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
// Move just below kTouchSlop should not recognize drag.
|
|
const Offset moveBy1 = Offset(kTouchSlop/ 2, kTouchSlop / 2);
|
|
expect(moveBy1.distance, lessThan(kTouchSlop));
|
|
await tester.drag(find.byKey(redContainer), moveBy1);
|
|
expect(dragCancelCount, 1);
|
|
expect(downDetails.single.localPosition, within(distance: 0.0001, from: const Offset(50, 75)));
|
|
expect(downDetails.single.globalPosition, within(distance: 0.0001, from: const Offset(400, 300)));
|
|
expect(endDetails, isEmpty);
|
|
expect(startDetails, isEmpty);
|
|
expect(updateDetails, isEmpty);
|
|
|
|
dragCancelCount = 0;
|
|
downDetails.clear();
|
|
endDetails.clear();
|
|
startDetails.clear();
|
|
updateDetails.clear();
|
|
|
|
// Move above kTouchSlop recognizes drag.
|
|
final TestGesture gesture = await tester.startGesture(tester.getCenter(find.byKey(redContainer)));
|
|
await gesture.moveBy(const Offset(kTouchSlop, kTouchSlop));
|
|
await gesture.moveBy(const Offset(-4, 3));
|
|
await gesture.up();
|
|
|
|
expect(dragCancelCount, 0);
|
|
expect(downDetails.single.localPosition, within(distance: 0.0001, from: const Offset(50, 75)));
|
|
expect(downDetails.single.globalPosition, within(distance: 0.0001, from: const Offset(400, 300)));
|
|
expect(endDetails, hasLength(1));
|
|
expect(startDetails, hasLength(1));
|
|
expect(updateDetails.single.globalPosition, within(distance: 0.0001, from: const Offset(400 + kTouchSlop - 4, 300 + kTouchSlop + 3)));
|
|
expect(updateDetails.single.delta, within(distance: 0.1, from: const Offset(0.0, 5.0))); // sqrt(3^2 + 4^2)
|
|
expect(updateDetails.single.primaryDelta, within<double>(distance: 0.1, from: 5.0)); // sqrt(3^2 + 4^2)
|
|
});
|
|
});
|
|
}
|