| // 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'; |
| |
| 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, |
| ); |
| }); |
| |
| testWidgets('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(); |
| }); |
| |
| testWidgets('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(); |
| }); |
| |
| testWidgets('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', () { |
| 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( |
| 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, |
| ); |
| }); |
| |
| testWidgets('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(); |
| }); |
| |
| testWidgets('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(); |
| }); |
| |
| testWidgets('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) |
| }); |
| }); |
| } |