Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
60a1b2b9
Unverified
Commit
60a1b2b9
authored
May 01, 2019
by
Jonah Williams
Committed by
GitHub
May 01, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Revert "Redo: Add buttons to gestures (#31819)" (#31912)
This reverts commit
fea2c7d6
.
parent
df4dc7cd
Changes
16
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
215 additions
and
1929 deletions
+215
-1929
converter.dart
packages/flutter/lib/src/gestures/converter.dart
+1
-5
events.dart
packages/flutter/lib/src/gestures/events.dart
+14
-81
long_press.dart
packages/flutter/lib/src/gestures/long_press.dart
+38
-112
monodrag.dart
packages/flutter/lib/src/gestures/monodrag.dart
+56
-172
multitap.dart
packages/flutter/lib/src/gestures/multitap.dart
+7
-54
tap.dart
packages/flutter/lib/src/gestures/tap.dart
+41
-171
gesture_detector.dart
packages/flutter/lib/src/widgets/gesture_detector.dart
+40
-187
debug_test.dart
packages/flutter/test/gestures/debug_test.dart
+1
-2
double_tap_test.dart
packages/flutter/test/gestures/double_tap_test.dart
+1
-192
drag_test.dart
packages/flutter/test/gestures/drag_test.dart
+8
-255
events_test.dart
packages/flutter/test/gestures/events_test.dart
+0
-14
gesture_binding_test.dart
packages/flutter/test/gestures/gesture_binding_test.dart
+1
-32
long_press_test.dart
packages/flutter/test/gestures/long_press_test.dart
+0
-270
tap_test.dart
packages/flutter/test/gestures/tap_test.dart
+0
-332
platform_view_test.dart
packages/flutter/test/widgets/platform_view_test.dart
+2
-8
test_pointer.dart
packages/flutter_test/lib/src/test_pointer.dart
+5
-42
No files found.
packages/flutter/lib/src/gestures/converter.dart
View file @
60a1b2b9
...
@@ -47,16 +47,12 @@ class _PointerState {
...
@@ -47,16 +47,12 @@ class _PointerState {
// https://github.com/flutter/flutter/issues/30454
// https://github.com/flutter/flutter/issues/30454
int
_synthesiseDownButtons
(
int
buttons
,
PointerDeviceKind
kind
)
{
int
_synthesiseDownButtons
(
int
buttons
,
PointerDeviceKind
kind
)
{
switch
(
kind
)
{
switch
(
kind
)
{
case
PointerDeviceKind
.
mouse
:
return
buttons
;
case
PointerDeviceKind
.
touch
:
case
PointerDeviceKind
.
touch
:
case
PointerDeviceKind
.
stylus
:
case
PointerDeviceKind
.
stylus
:
case
PointerDeviceKind
.
invertedStylus
:
case
PointerDeviceKind
.
invertedStylus
:
return
buttons
|
kPrimaryButton
;
return
buttons
|
kPrimaryButton
;
default
:
default
:
// We have no information about the device but we know we never want
return
buttons
;
// buttons to be 0 when the pointer is down.
return
buttons
==
0
?
kPrimaryButton
:
buttons
;
}
}
}
}
...
...
packages/flutter/lib/src/gestures/events.dart
View file @
60a1b2b9
...
@@ -8,35 +8,22 @@ import 'package:flutter/foundation.dart';
...
@@ -8,35 +8,22 @@ import 'package:flutter/foundation.dart';
export
'dart:ui'
show
Offset
,
PointerDeviceKind
;
export
'dart:ui'
show
Offset
,
PointerDeviceKind
;
/// The bit of [PointerEvent.buttons] that corresponds to
a cross-device
/// The bit of [PointerEvent.buttons] that corresponds to
the "primary
///
behavior of "primary operation"
.
///
action" on any device
.
///
///
/// More specifially,
it includes:
/// More specifially,
///
///
/// *
[kTouchContact]: The pointer contacts the touch
screen.
/// *
For touch screen, it's when the pointer contacts the
screen.
/// *
[kStylusContact]: The stylus
contacts the screen.
/// *
For stylus and inverted stylus, it's when the pen
contacts the screen.
/// *
[kPrimaryMouseButton]: The primary mouse button
.
/// *
For mouse, it's when the primary button is pressed
.
///
///
/// See also:
/// See also:
///
///
/// * [kSecondaryButton], which describes a cross-device behavior of
/// * [kTouchContact]: an alias of this constant when used by touch screen.
/// "secondary operation".
/// * [kStylusContact]: an alias of this constant when used by stylus.
/// * [kPrimaryMouseButton]: an alias of this constant when used by mouse.
const
int
kPrimaryButton
=
0x01
;
const
int
kPrimaryButton
=
0x01
;
/// The bit of [PointerEvent.buttons] that corresponds to a cross-device
/// behavior of "secondary operation".
///
/// It is equivalent to:
///
/// * [kPrimaryStylusButton]: The stylus contacts the screen.
/// * [kSecondaryMouseButton]: The primary mouse button.
///
/// See also:
///
/// * [kPrimaryButton], which describes a cross-device behavior of
/// "primary operation".
const
int
kSecondaryButton
=
0x02
;
/// The bit of [PointerEvent.buttons] that corresponds to the primary mouse button.
/// The bit of [PointerEvent.buttons] that corresponds to the primary mouse button.
///
///
/// The primary mouse button is typically the left button on the top of the
/// The primary mouse button is typically the left button on the top of the
...
@@ -44,40 +31,28 @@ const int kSecondaryButton = 0x02;
...
@@ -44,40 +31,28 @@ const int kSecondaryButton = 0x02;
///
///
/// See also:
/// See also:
///
///
/// * [kPrimaryButton], which has the same value but describes its cross-device
/// * [kTouchContact]: an alias of this constant when used by touch screen.
/// concept.
const
int
kPrimaryMouseButton
=
kPrimaryButton
;
const
int
kPrimaryMouseButton
=
kPrimaryButton
;
/// The bit of [PointerEvent.buttons] that corresponds to the secondary mouse button.
/// The bit of [PointerEvent.buttons] that corresponds to the secondary mouse button.
///
///
/// The secondary mouse button is typically the right button on the top of the
/// The secondary mouse button is typically the right button on the top of the
/// mouse but can be reconfigured to be a different physical button.
/// mouse but can be reconfigured to be a different physical button.
///
const
int
kSecondaryMouseButton
=
0x02
;
/// See also:
///
/// * [kSecondaryButton], which has the same value but describes its cross-device
/// concept.
const
int
kSecondaryMouseButton
=
kSecondaryButton
;
/// The bit of [PointerEvent.buttons] that corresponds to when a stylus
/// The bit of [PointerEvent.buttons] that corresponds to when a stylus
/// contacting the screen.
/// contacting the screen.
///
///
/// See also:
/// See also:
///
///
/// * [kPrimaryButton], which has the same value but describes its cross-device
/// * [kPrimaryButton]: an alias of this constant for any device.
/// concept.
const
int
kStylusContact
=
kPrimaryButton
;
const
int
kStylusContact
=
kPrimaryButton
;
/// The bit of [PointerEvent.buttons] that corresponds to the primary stylus button.
/// The bit of [PointerEvent.buttons] that corresponds to the primary stylus button.
///
///
/// The primary stylus button is typically the top of the stylus and near the
/// The primary stylus button is typically the top of the stylus and near the
/// tip but can be reconfigured to be a different physical button.
/// tip but can be reconfigured to be a different physical button.
///
const
int
kPrimaryStylusButton
=
0x02
;
/// See also:
///
/// * [kSecondaryButton], which has the same value but describes its cross-device
/// concept.
const
int
kPrimaryStylusButton
=
kSecondaryButton
;
/// The bit of [PointerEvent.buttons] that corresponds to the middle mouse button.
/// The bit of [PointerEvent.buttons] that corresponds to the middle mouse button.
///
///
...
@@ -109,8 +84,7 @@ const int kForwardMouseButton = 0x10;
...
@@ -109,8 +84,7 @@ const int kForwardMouseButton = 0x10;
///
///
/// See also:
/// See also:
///
///
/// * [kPrimaryButton], which has the same value but describes its cross-device
/// * [kPrimaryButton]: an alias of this constant for any device.
/// concept.
const
int
kTouchContact
=
kPrimaryButton
;
const
int
kTouchContact
=
kPrimaryButton
;
/// The bit of [PointerEvent.buttons] that corresponds to the nth mouse button.
/// The bit of [PointerEvent.buttons] that corresponds to the nth mouse button.
...
@@ -130,47 +104,6 @@ int nthMouseButton(int number) => (kPrimaryMouseButton << (number - 1)) & kMaxUn
...
@@ -130,47 +104,6 @@ int nthMouseButton(int number) => (kPrimaryMouseButton << (number - 1)) & kMaxUn
/// for some stylus buttons.
/// for some stylus buttons.
int
nthStylusButton
(
int
number
)
=>
(
kPrimaryStylusButton
<<
(
number
-
1
))
&
kMaxUnsignedSMI
;
int
nthStylusButton
(
int
number
)
=>
(
kPrimaryStylusButton
<<
(
number
-
1
))
&
kMaxUnsignedSMI
;
/// Returns the button of `buttons` with the smallest integer.
///
/// The `buttons` parameter is a bitfield where each set bit represents a button.
/// This function returns the set bit closest to the least significant bit.
///
/// It returns zero when `buttons` is zero.
///
/// Example:
///
/// ```dart
/// assert(rightmostButton(0x1) == 0x1);
/// assert(rightmostButton(0x11) == 0x1);
/// assert(rightmostButton(0) == 0);
/// ```
///
/// See also:
///
/// * [isSingleButton], which checks if a `buttons` contains exactly one button.
int
smallestButton
(
int
buttons
)
=>
buttons
&
(-
buttons
);
/// Returns whether `buttons` contains one and only one button.
///
/// The `buttons` parameter is a bitfield where each set bit represents a button.
/// This function returns whether there is only one set bit in the given integer.
///
/// It returns false when `buttons` is zero.
///
/// Example:
///
/// ```dart
/// assert(isSingleButton(0x1) == true);
/// assert(isSingleButton(0x11) == false);
/// assert(isSingleButton(0) == false);
/// ```
///
/// See also:
///
/// * [smallestButton], which returns the button in a `buttons` bitfield with
/// the smallest integer button.
bool
isSingleButton
(
int
buttons
)
=>
buttons
!=
0
&&
(
smallestButton
(
buttons
)
==
buttons
);
/// Base class for touch, stylus, or mouse events.
/// Base class for touch, stylus, or mouse events.
///
///
/// Pointer events operate in the coordinate space of the screen, scaled to
/// Pointer events operate in the coordinate space of the screen, scaled to
...
...
packages/flutter/lib/src/gestures/long_press.dart
View file @
60a1b2b9
...
@@ -109,10 +109,6 @@ class LongPressEndDetails {
...
@@ -109,10 +109,6 @@ class LongPressEndDetails {
/// until it's recognized. Once the gesture is accepted, the finger can be
/// until it's recognized. Once the gesture is accepted, the finger can be
/// moved, triggering [onLongPressMoveUpdate] callbacks, unless the
/// moved, triggering [onLongPressMoveUpdate] callbacks, unless the
/// [postAcceptSlopTolerance] constructor argument is specified.
/// [postAcceptSlopTolerance] constructor argument is specified.
///
/// [LongPressGestureRecognizer] competes on pointer events of [kPrimaryButton]
/// only when it has at least one non-null callback. If it has no callbacks, it
/// is a no-op.
class
LongPressGestureRecognizer
extends
PrimaryPointerGestureRecognizer
{
class
LongPressGestureRecognizer
extends
PrimaryPointerGestureRecognizer
{
/// Creates a long-press gesture recognizer.
/// Creates a long-press gesture recognizer.
///
///
...
@@ -137,159 +133,89 @@ class LongPressGestureRecognizer extends PrimaryPointerGestureRecognizer {
...
@@ -137,159 +133,89 @@ class LongPressGestureRecognizer extends PrimaryPointerGestureRecognizer {
);
);
bool
_longPressAccepted
=
false
;
bool
_longPressAccepted
=
false
;
Offset
_longPressOrigin
;
Offset
_longPressOrigin
;
// The buttons sent by `PointerDownEvent`. If a `PointerMoveEvent` comes with a
// different set of buttons, the gesture is canceled.
int
_initialButtons
;
/// Called when a long press gesture
by a primary button
has been recognized.
/// Called when a long press gesture has been recognized.
///
///
/// See also:
/// See also:
///
///
/// * [kPrimaryButton], the button this callback responds to.
/// * [onLongPressStart], which has the same timing but has data for the
/// * [onLongPressStart], which has the same timing but has data for the
/// press location.
/// press location.
GestureLongPressCallback
onLongPress
;
GestureLongPressCallback
onLongPress
;
/// Call
ed when a long press gesture by a primary button has been recognized
.
/// Call
back for long press start with gesture location
.
///
///
/// See also:
/// See also:
///
///
/// * [kPrimaryButton], the button this callback responds to.
/// * [onLongPress], which has the same timing but without the location data.
/// * [onLongPress], which has the same timing but without details.
/// * [LongPressStartDetails], which is passed as an argument to this callback.
GestureLongPressStartCallback
onLongPressStart
;
GestureLongPressStartCallback
onLongPressStart
;
/// Called when moving after the long press by a primary button is recognized.
/// Callback for moving the gesture after the lang press is recognized.
///
/// See also:
///
/// * [kPrimaryButton], the button this callback responds to.
/// * [LongPressMoveUpdateDetails], which is passed as an argument to this
/// callback.
GestureLongPressMoveUpdateCallback
onLongPressMoveUpdate
;
GestureLongPressMoveUpdateCallback
onLongPressMoveUpdate
;
/// Called when the pointer stops contacting the screen after a long-press
/// Called when the pointer stops contacting the screen after the long-press.
/// by a primary button.
///
///
/// See also:
/// See also:
///
///
/// * [kPrimaryButton], the button this callback responds to.
/// * [onLongPressEnd], which has the same timing but has data for the up
/// * [onLongPressEnd], which has the same timing but has data for the up
/// gesture location.
/// gesture location.
GestureLongPressUpCallback
onLongPressUp
;
GestureLongPressUpCallback
onLongPressUp
;
/// Called when the pointer stops contacting the screen after a long-press
/// Callback for long press end with gesture location.
/// by a primary button.
///
///
/// See also:
/// See also:
///
///
/// * [kPrimaryButton], the button this callback responds to.
/// * [onLongPressUp], which has the same timing but without the location data.
/// * [onLongPressUp], which has the same timing, but without details.
/// * [LongPressEndDetails], which is passed as an argument to this
/// callback.
GestureLongPressEndCallback
onLongPressEnd
;
GestureLongPressEndCallback
onLongPressEnd
;
@override
bool
isPointerAllowed
(
PointerDownEvent
event
)
{
switch
(
event
.
buttons
)
{
case
kPrimaryButton:
if
(
onLongPressStart
==
null
&&
onLongPress
==
null
&&
onLongPressMoveUpdate
==
null
&&
onLongPressEnd
==
null
&&
onLongPressUp
==
null
)
return
false
;
break
;
default
:
return
false
;
}
return
super
.
isPointerAllowed
(
event
);
}
@override
@override
void
didExceedDeadline
()
{
void
didExceedDeadline
()
{
// Exceeding the deadline puts the gesture in the accepted state.
resolve
(
GestureDisposition
.
accepted
);
resolve
(
GestureDisposition
.
accepted
);
_longPressAccepted
=
true
;
_longPressAccepted
=
true
;
super
.
acceptGesture
(
primaryPointer
);
super
.
acceptGesture
(
primaryPointer
);
_checkLongPressStart
();
if
(
onLongPress
!=
null
)
{
invokeCallback
<
void
>(
'onLongPress'
,
onLongPress
);
}
if
(
onLongPressStart
!=
null
)
{
invokeCallback
<
void
>(
'onLongPressStart'
,
()
{
onLongPressStart
(
LongPressStartDetails
(
globalPosition:
_longPressOrigin
,
));
});
}
}
}
@override
@override
void
handlePrimaryPointer
(
PointerEvent
event
)
{
void
handlePrimaryPointer
(
PointerEvent
event
)
{
if
(
event
is
PointerUpEvent
)
{
if
(
event
is
PointerUpEvent
)
{
if
(
_longPressAccepted
==
true
)
{
if
(
_longPressAccepted
==
true
)
{
_checkLongPressEnd
(
event
);
if
(
onLongPressUp
!=
null
)
{
invokeCallback
<
void
>(
'onLongPressUp'
,
onLongPressUp
);
}
if
(
onLongPressEnd
!=
null
)
{
invokeCallback
<
void
>(
'onLongPressEnd'
,
()
{
onLongPressEnd
(
LongPressEndDetails
(
globalPosition:
event
.
position
,
));
});
}
_longPressAccepted
=
false
;
}
else
{
}
else
{
// Pointer is lifted before timeout.
resolve
(
GestureDisposition
.
rejected
);
resolve
(
GestureDisposition
.
rejected
);
}
}
_reset
();
}
else
if
(
event
is
PointerDownEvent
||
event
is
PointerCancelEvent
)
{
}
else
if
(
event
is
PointerCancelEvent
)
{
_reset
();
}
else
if
(
event
is
PointerDownEvent
)
{
// The first touch.
// The first touch.
_longPressAccepted
=
false
;
_longPressOrigin
=
event
.
position
;
_longPressOrigin
=
event
.
position
;
_initialButtons
=
event
.
buttons
;
}
else
if
(
event
is
PointerMoveEvent
&&
_longPressAccepted
&&
onLongPressMoveUpdate
!=
null
)
{
}
else
if
(
event
is
PointerMoveEvent
)
{
invokeCallback
<
void
>(
'onLongPressMoveUpdate'
,
()
{
if
(
event
.
buttons
!=
_initialButtons
)
{
onLongPressMoveUpdate
(
LongPressMoveUpdateDetails
(
resolve
(
GestureDisposition
.
rejected
);
globalPosition:
event
.
position
,
stopTrackingPointer
(
primaryPointer
);
offsetFromOrigin:
event
.
position
-
_longPressOrigin
,
}
else
if
(
_longPressAccepted
)
{
));
_checkLongPressMoveUpdate
(
event
);
});
}
}
}
void
_checkLongPressStart
()
{
assert
(
_initialButtons
==
kPrimaryButton
);
final
LongPressStartDetails
details
=
LongPressStartDetails
(
globalPosition:
_longPressOrigin
,
);
if
(
onLongPressStart
!=
null
)
invokeCallback
<
void
>(
'onLongPressStart'
,
()
=>
onLongPressStart
(
details
));
if
(
onLongPress
!=
null
)
invokeCallback
<
void
>(
'onLongPress'
,
onLongPress
);
}
void
_checkLongPressMoveUpdate
(
PointerEvent
event
)
{
assert
(
_initialButtons
==
kPrimaryButton
);
final
LongPressMoveUpdateDetails
details
=
LongPressMoveUpdateDetails
(
globalPosition:
event
.
position
,
offsetFromOrigin:
event
.
position
-
_longPressOrigin
,
);
if
(
onLongPressMoveUpdate
!=
null
)
invokeCallback
<
void
>(
'onLongPressMoveUpdate'
,
()
=>
onLongPressMoveUpdate
(
details
));
}
void
_checkLongPressEnd
(
PointerEvent
event
)
{
assert
(
_initialButtons
==
kPrimaryButton
);
final
LongPressEndDetails
details
=
LongPressEndDetails
(
globalPosition:
event
.
position
,
);
if
(
onLongPressEnd
!=
null
)
invokeCallback
<
void
>(
'onLongPressEnd'
,
()
=>
onLongPressEnd
(
details
));
if
(
onLongPressUp
!=
null
)
invokeCallback
<
void
>(
'onLongPressUp'
,
onLongPressUp
);
}
void
_reset
()
{
_longPressAccepted
=
false
;
_longPressOrigin
=
null
;
_initialButtons
=
null
;
}
@override
void
resolve
(
GestureDisposition
disposition
)
{
if
(
_longPressAccepted
&&
disposition
==
GestureDisposition
.
rejected
)
{
// This can happen if the gesture has been canceled. For example when
// the buttons have changed.
_reset
();
}
}
super
.
resolve
(
disposition
);
}
}
@override
@override
...
...
packages/flutter/lib/src/gestures/monodrag.dart
View file @
60a1b2b9
...
@@ -43,10 +43,6 @@ typedef GestureDragCancelCallback = void Function();
...
@@ -43,10 +43,6 @@ typedef GestureDragCancelCallback = void Function();
/// consider using one of its subclasses to recognize specific types for drag
/// consider using one of its subclasses to recognize specific types for drag
/// gestures.
/// gestures.
///
///
/// [DragGestureRecognizer] competes on pointer events of [kPrimaryButton]
/// only when it has at least one non-null callback. If it has no callbacks, it
/// is a no-op.
///
/// See also:
/// See also:
///
///
/// * [HorizontalDragGestureRecognizer], for left and right drags.
/// * [HorizontalDragGestureRecognizer], for left and right drags.
...
@@ -88,20 +84,13 @@ abstract class DragGestureRecognizer extends OneSequenceGestureRecognizer {
...
@@ -88,20 +84,13 @@ abstract class DragGestureRecognizer extends OneSequenceGestureRecognizer {
/// at (510.0, 500.0).
/// at (510.0, 500.0).
DragStartBehavior
dragStartBehavior
;
DragStartBehavior
dragStartBehavior
;
/// A pointer has contacted the screen with a primary button and might begin
/// A pointer has contacted the screen and might begin to move.
/// to move.
///
///
/// The position of the pointer is provided in the callback's `details`
/// The position of the pointer is provided in the callback's `details`
/// argument, which is a [DragDownDetails] object.
/// argument, which is a [DragDownDetails] object.
///
/// See also:
///
/// * [kPrimaryButton], the button this callback responds to.
/// * [DragDownDetails], which is passed as an argument to this callback.
GestureDragDownCallback
onDown
;
GestureDragDownCallback
onDown
;
/// A pointer has contacted the screen with a primary button and has begun to
/// A pointer has contacted the screen and has begun to move.
/// move.
///
///
/// The position of the pointer is provided in the callback's `details`
/// The position of the pointer is provided in the callback's `details`
/// argument, which is a [DragStartDetails] object.
/// argument, which is a [DragStartDetails] object.
...
@@ -110,43 +99,23 @@ abstract class DragGestureRecognizer extends OneSequenceGestureRecognizer {
...
@@ -110,43 +99,23 @@ abstract class DragGestureRecognizer extends OneSequenceGestureRecognizer {
/// called on the initial touch down, if set to [DragStartBehavior.down] or
/// called on the initial touch down, if set to [DragStartBehavior.down] or
/// when the drag gesture is first detected, if set to
/// when the drag gesture is first detected, if set to
/// [DragStartBehavior.start].
/// [DragStartBehavior.start].
///
/// See also:
///
/// * [kPrimaryButton], the button this callback responds to.
/// * [DragStartDetails], which is passed as an argument to this callback.
GestureDragStartCallback
onStart
;
GestureDragStartCallback
onStart
;
/// A pointer that is in contact with the screen with a primary button and
/// A pointer that is in contact with the screen and moving has moved again.
/// moving has moved again.
///
///
/// The distance travelled by the pointer since the last update is provided in
/// The distance travelled by the pointer since the last update is provided in
/// the callback's `details` argument, which is a [DragUpdateDetails] object.
/// the callback's `details` argument, which is a [DragUpdateDetails] object.
///
/// See also:
///
/// * [kPrimaryButton], the button this callback responds to.
/// * [DragUpdateDetails], which is passed as an argument to this callback.
GestureDragUpdateCallback
onUpdate
;
GestureDragUpdateCallback
onUpdate
;
/// A pointer that was previously in contact with the screen
with a primary
/// A pointer that was previously in contact with the screen
and moving is no
///
button and moving is no longer in contact with the screen and was moving
///
longer in contact with the screen and was moving at a specific velocity
///
at a specific velocity
when it stopped contacting the screen.
/// when it stopped contacting the screen.
///
///
/// The velocity is provided in the callback's `details` argument, which is a
/// The velocity is provided in the callback's `details` argument, which is a
/// [DragEndDetails] object.
/// [DragEndDetails] object.
///
/// See also:
///
/// * [kPrimaryButton], the button this callback responds to.
/// * [DragEndDetails], which is passed as an argument to this callback.
GestureDragEndCallback
onEnd
;
GestureDragEndCallback
onEnd
;
/// The pointer that previously triggered [onDown] did not complete.
/// The pointer that previously triggered [onDown] did not complete.
///
/// See also:
///
/// * [kPrimaryButton], the button this callback responds to.
GestureDragCancelCallback
onCancel
;
GestureDragCancelCallback
onCancel
;
/// The minimum distance an input pointer drag must have moved to
/// The minimum distance an input pointer drag must have moved to
...
@@ -172,9 +141,6 @@ abstract class DragGestureRecognizer extends OneSequenceGestureRecognizer {
...
@@ -172,9 +141,6 @@ abstract class DragGestureRecognizer extends OneSequenceGestureRecognizer {
Offset
_initialPosition
;
Offset
_initialPosition
;
Offset
_pendingDragOffset
;
Offset
_pendingDragOffset
;
Duration
_lastPendingEventTimestamp
;
Duration
_lastPendingEventTimestamp
;
// The buttons sent by `PointerDownEvent`. If a `PointerMoveEvent` comes with a
// different set of buttons, the gesture is canceled.
int
_initialButtons
;
bool
_isFlingGesture
(
VelocityEstimate
estimate
);
bool
_isFlingGesture
(
VelocityEstimate
estimate
);
Offset
_getDeltaForDetails
(
Offset
delta
);
Offset
_getDeltaForDetails
(
Offset
delta
);
...
@@ -183,30 +149,6 @@ abstract class DragGestureRecognizer extends OneSequenceGestureRecognizer {
...
@@ -183,30 +149,6 @@ abstract class DragGestureRecognizer extends OneSequenceGestureRecognizer {
final
Map
<
int
,
VelocityTracker
>
_velocityTrackers
=
<
int
,
VelocityTracker
>{};
final
Map
<
int
,
VelocityTracker
>
_velocityTrackers
=
<
int
,
VelocityTracker
>{};
@override
bool
isPointerAllowed
(
PointerEvent
event
)
{
if
(
_initialButtons
==
null
)
{
switch
(
event
.
buttons
)
{
case
kPrimaryButton:
if
(
onDown
==
null
&&
onStart
==
null
&&
onUpdate
==
null
&&
onEnd
==
null
&&
onCancel
==
null
)
return
false
;
break
;
default
:
return
false
;
}
}
else
{
// There can be multiple drags simultaneously. Their effects are combined.
if
(
event
.
buttons
!=
_initialButtons
)
{
return
false
;
}
}
return
super
.
isPointerAllowed
(
event
);
}
@override
@override
void
addAllowedPointer
(
PointerEvent
event
)
{
void
addAllowedPointer
(
PointerEvent
event
)
{
startTrackingPointer
(
event
.
pointer
);
startTrackingPointer
(
event
.
pointer
);
...
@@ -214,10 +156,10 @@ abstract class DragGestureRecognizer extends OneSequenceGestureRecognizer {
...
@@ -214,10 +156,10 @@ abstract class DragGestureRecognizer extends OneSequenceGestureRecognizer {
if
(
_state
==
_DragState
.
ready
)
{
if
(
_state
==
_DragState
.
ready
)
{
_state
=
_DragState
.
possible
;
_state
=
_DragState
.
possible
;
_initialPosition
=
event
.
position
;
_initialPosition
=
event
.
position
;
_initialButtons
=
event
.
buttons
;
_pendingDragOffset
=
Offset
.
zero
;
_pendingDragOffset
=
Offset
.
zero
;
_lastPendingEventTimestamp
=
event
.
timeStamp
;
_lastPendingEventTimestamp
=
event
.
timeStamp
;
_checkDown
();
if
(
onDown
!=
null
)
invokeCallback
<
void
>(
'onDown'
,
()
=>
onDown
(
DragDownDetails
(
globalPosition:
_initialPosition
)));
}
else
if
(
_state
==
_DragState
.
accepted
)
{
}
else
if
(
_state
==
_DragState
.
accepted
)
{
resolve
(
GestureDisposition
.
accepted
);
resolve
(
GestureDisposition
.
accepted
);
}
}
...
@@ -234,19 +176,16 @@ abstract class DragGestureRecognizer extends OneSequenceGestureRecognizer {
...
@@ -234,19 +176,16 @@ abstract class DragGestureRecognizer extends OneSequenceGestureRecognizer {
}
}
if
(
event
is
PointerMoveEvent
)
{
if
(
event
is
PointerMoveEvent
)
{
if
(
event
.
buttons
!=
_initialButtons
)
{
resolve
(
GestureDisposition
.
rejected
);
stopTrackingPointer
(
event
.
pointer
);
return
;
}
final
Offset
delta
=
event
.
delta
;
final
Offset
delta
=
event
.
delta
;
if
(
_state
==
_DragState
.
accepted
)
{
if
(
_state
==
_DragState
.
accepted
)
{
_checkUpdate
(
if
(
onUpdate
!=
null
)
{
sourceTimeStamp:
event
.
timeStamp
,
invokeCallback
<
void
>(
'onUpdate'
,
()
=>
onUpdate
(
DragUpdateDetails
(
delta:
_getDeltaForDetails
(
delta
),
sourceTimeStamp:
event
.
timeStamp
,
primaryDelta:
_getPrimaryValueFromOffset
(
delta
),
delta:
_getDeltaForDetails
(
delta
),
globalPosition:
event
.
position
,
primaryDelta:
_getPrimaryValueFromOffset
(
delta
),
);
globalPosition:
event
.
position
,
)));
}
}
else
{
}
else
{
_pendingDragOffset
+=
delta
;
_pendingDragOffset
+=
delta
;
_lastPendingEventTimestamp
=
event
.
timeStamp
;
_lastPendingEventTimestamp
=
event
.
timeStamp
;
...
@@ -275,14 +214,19 @@ abstract class DragGestureRecognizer extends OneSequenceGestureRecognizer {
...
@@ -275,14 +214,19 @@ abstract class DragGestureRecognizer extends OneSequenceGestureRecognizer {
}
}
_pendingDragOffset
=
Offset
.
zero
;
_pendingDragOffset
=
Offset
.
zero
;
_lastPendingEventTimestamp
=
null
;
_lastPendingEventTimestamp
=
null
;
_checkStart
(
timestamp
);
if
(
onStart
!=
null
)
{
if
(
updateDelta
!=
Offset
.
zero
)
{
invokeCallback
<
void
>(
'onStart'
,
()
=>
onStart
(
DragStartDetails
(
_checkUpdate
(
sourceTimeStamp:
timestamp
,
globalPosition:
_initialPosition
,
)));
}
if
(
updateDelta
!=
Offset
.
zero
&&
onUpdate
!=
null
)
{
invokeCallback
<
void
>(
'onUpdate'
,
()
=>
onUpdate
(
DragUpdateDetails
(
sourceTimeStamp:
timestamp
,
sourceTimeStamp:
timestamp
,
delta:
updateDelta
,
delta:
updateDelta
,
primaryDelta:
_getPrimaryValueFromOffset
(
updateDelta
),
primaryDelta:
_getPrimaryValueFromOffset
(
updateDelta
),
globalPosition:
_initialPosition
+
updateDelta
,
// Only adds delta for down behaviour
globalPosition:
_initialPosition
+
updateDelta
,
// Only adds delta for down behaviour
);
)
))
;
}
}
}
}
}
}
...
@@ -294,101 +238,41 @@ abstract class DragGestureRecognizer extends OneSequenceGestureRecognizer {
...
@@ -294,101 +238,41 @@ abstract class DragGestureRecognizer extends OneSequenceGestureRecognizer {
@override
@override
void
didStopTrackingLastPointer
(
int
pointer
)
{
void
didStopTrackingLastPointer
(
int
pointer
)
{
assert
(
_state
!=
_DragState
.
ready
);
if
(
_state
==
_DragState
.
possible
)
{
switch
(
_state
)
{
resolve
(
GestureDisposition
.
rejected
);
case
_DragState
.
ready
:
_state
=
_DragState
.
ready
;
break
;
if
(
onCancel
!=
null
)
invokeCallback
<
void
>(
'onCancel'
,
onCancel
);
case
_DragState
.
possible
:
return
;
resolve
(
GestureDisposition
.
rejected
);
_checkCancel
();
break
;
case
_DragState
.
accepted
:
_checkEnd
(
pointer
);
break
;
}
}
_velocityTrackers
.
clear
();
final
bool
wasAccepted
=
_state
==
_DragState
.
accepted
;
_initialButtons
=
null
;
_state
=
_DragState
.
ready
;
_state
=
_DragState
.
ready
;
}
if
(
wasAccepted
&&
onEnd
!=
null
)
{
final
VelocityTracker
tracker
=
_velocityTrackers
[
pointer
];
void
_checkDown
()
{
assert
(
tracker
!=
null
);
assert
(
_initialButtons
==
kPrimaryButton
);
final
DragDownDetails
details
=
DragDownDetails
(
globalPosition:
_initialPosition
,
);
if
(
onDown
!=
null
)
invokeCallback
<
void
>(
'onDown'
,
()
=>
onDown
(
details
));
}
void
_checkStart
(
Duration
timestamp
)
{
assert
(
_initialButtons
==
kPrimaryButton
);
final
DragStartDetails
details
=
DragStartDetails
(
sourceTimeStamp:
timestamp
,
globalPosition:
_initialPosition
,
);
if
(
onStart
!=
null
)
invokeCallback
<
void
>(
'onStart'
,
()
=>
onStart
(
details
));
}
void
_checkUpdate
({
Duration
sourceTimeStamp
,
Offset
delta
,
double
primaryDelta
,
Offset
globalPosition
,
})
{
assert
(
_initialButtons
==
kPrimaryButton
);
final
DragUpdateDetails
details
=
DragUpdateDetails
(
sourceTimeStamp:
sourceTimeStamp
,
delta:
delta
,
primaryDelta:
primaryDelta
,
globalPosition:
globalPosition
,
);
if
(
onUpdate
!=
null
)
invokeCallback
<
void
>(
'onUpdate'
,
()
=>
onUpdate
(
details
));
}
void
_checkEnd
(
int
pointer
)
{
assert
(
_initialButtons
==
kPrimaryButton
);
if
(
onEnd
==
null
)
return
;
final
VelocityTracker
tracker
=
_velocityTrackers
[
pointer
];
final
VelocityEstimate
estimate
=
tracker
.
getVelocityEstimate
();
assert
(
tracker
!=
null
);
if
(
estimate
!=
null
&&
_isFlingGesture
(
estimate
))
{
final
Velocity
velocity
=
Velocity
(
pixelsPerSecond:
estimate
.
pixelsPerSecond
)
DragEndDetails
details
;
.
clampMagnitude
(
minFlingVelocity
??
kMinFlingVelocity
,
maxFlingVelocity
??
kMaxFlingVelocity
);
void
Function
()
debugReport
;
invokeCallback
<
void
>(
'onEnd'
,
()
=>
onEnd
(
DragEndDetails
(
velocity:
velocity
,
final
VelocityEstimate
estimate
=
tracker
.
getVelocityEstimate
();
primaryVelocity:
_getPrimaryValueFromOffset
(
velocity
.
pixelsPerSecond
),
if
(
estimate
!=
null
&&
_isFlingGesture
(
estimate
))
{
)),
debugReport:
()
{
final
Velocity
velocity
=
Velocity
(
pixelsPerSecond:
estimate
.
pixelsPerSecond
)
return
'
$estimate
; fling at
$velocity
.'
;
.
clampMagnitude
(
minFlingVelocity
??
kMinFlingVelocity
,
maxFlingVelocity
??
kMaxFlingVelocity
);
});
details
=
DragEndDetails
(
}
else
{
velocity:
velocity
,
invokeCallback
<
void
>(
'onEnd'
,
()
=>
onEnd
(
DragEndDetails
(
primaryVelocity:
_getPrimaryValueFromOffset
(
velocity
.
pixelsPerSecond
),
velocity:
Velocity
.
zero
,
);
primaryVelocity:
0.0
,
debugReport
=
()
{
)),
debugReport:
()
{
return
'
$estimate
; fling at
$velocity
.'
;
if
(
estimate
==
null
)
};
return
'Could not estimate velocity.'
;
}
else
{
return
'
$estimate
; judged to not be a fling.'
;
details
=
DragEndDetails
(
});
velocity:
Velocity
.
zero
,
}
primaryVelocity:
0.0
,
);
debugReport
=
()
{
if
(
estimate
==
null
)
return
'Could not estimate velocity.'
;
return
'
$estimate
; judged to not be a fling.'
;
};
}
}
invokeCallback
<
void
>(
'onEnd'
,
()
=>
onEnd
(
details
),
debugReport:
debugReport
);
_velocityTrackers
.
clear
();
}
void
_checkCancel
()
{
assert
(
_initialButtons
==
kPrimaryButton
);
if
(
onCancel
!=
null
)
invokeCallback
<
void
>(
'onCancel'
,
onCancel
);
}
}
@override
@override
...
...
packages/flutter/lib/src/gestures/multitap.dart
View file @
60a1b2b9
...
@@ -16,10 +16,6 @@ import 'tap.dart';
...
@@ -16,10 +16,6 @@ import 'tap.dart';
/// Signature for callback when the user has tapped the screen at the same
/// Signature for callback when the user has tapped the screen at the same
/// location twice in quick succession.
/// location twice in quick succession.
///
/// See also:
///
/// * [GestureDetector.onDoubleTap], which matches this signature.
typedef
GestureDoubleTapCallback
=
void
Function
();
typedef
GestureDoubleTapCallback
=
void
Function
();
/// Signature used by [MultiTapGestureRecognizer] for when a pointer that might
/// Signature used by [MultiTapGestureRecognizer] for when a pointer that might
...
@@ -64,16 +60,13 @@ class _TapTracker {
...
@@ -64,16 +60,13 @@ class _TapTracker {
@required
Duration
doubleTapMinTime
,
@required
Duration
doubleTapMinTime
,
})
:
assert
(
doubleTapMinTime
!=
null
),
})
:
assert
(
doubleTapMinTime
!=
null
),
assert
(
event
!=
null
),
assert
(
event
!=
null
),
assert
(
event
.
buttons
!=
null
),
pointer
=
event
.
pointer
,
pointer
=
event
.
pointer
,
_initialPosition
=
event
.
position
,
_initialPosition
=
event
.
position
,
initialButtons
=
event
.
buttons
,
_doubleTapMinTimeCountdown
=
_CountdownZoned
(
duration:
doubleTapMinTime
);
_doubleTapMinTimeCountdown
=
_CountdownZoned
(
duration:
doubleTapMinTime
);
final
int
pointer
;
final
int
pointer
;
final
GestureArenaEntry
entry
;
final
GestureArenaEntry
entry
;
final
Offset
_initialPosition
;
final
Offset
_initialPosition
;
final
int
initialButtons
;
final
_CountdownZoned
_doubleTapMinTimeCountdown
;
final
_CountdownZoned
_doubleTapMinTimeCountdown
;
bool
_isTrackingPointer
=
false
;
bool
_isTrackingPointer
=
false
;
...
@@ -100,18 +93,10 @@ class _TapTracker {
...
@@ -100,18 +93,10 @@ class _TapTracker {
bool
hasElapsedMinTime
()
{
bool
hasElapsedMinTime
()
{
return
_doubleTapMinTimeCountdown
.
timeout
;
return
_doubleTapMinTimeCountdown
.
timeout
;
}
}
bool
hasSameButton
(
PointerDownEvent
event
)
{
return
event
.
buttons
==
initialButtons
;
}
}
}
/// Recognizes when the user has tapped the screen at the same location twice in
/// Recognizes when the user has tapped the screen at the same location twice in
/// quick succession.
/// quick succession.
///
/// [DoubleTapGestureRecognizer] competes on pointer events of [kPrimaryButton]
/// only when it has a non-null callback. If it has no callbacks, it is a no-op.
///
class
DoubleTapGestureRecognizer
extends
GestureRecognizer
{
class
DoubleTapGestureRecognizer
extends
GestureRecognizer
{
/// Create a gesture recognizer for double taps.
/// Create a gesture recognizer for double taps.
///
///
...
@@ -141,53 +126,26 @@ class DoubleTapGestureRecognizer extends GestureRecognizer {
...
@@ -141,53 +126,26 @@ class DoubleTapGestureRecognizer extends GestureRecognizer {
// - The long timer between taps expires
// - The long timer between taps expires
// - The gesture arena decides we have been rejected wholesale
// - The gesture arena decides we have been rejected wholesale
/// Called when the user has tapped the screen with a primary button at the
/// Called when the user has tapped the screen at the same location twice in
/// same location twice in quick succession.
/// quick succession.
///
/// This triggers when the pointer stops contacting the device after the 2nd tap,
/// immediately after [onDoubleTapUp].
///
/// See also:
///
/// * [kPrimaryButton], the button this callback responds to.
GestureDoubleTapCallback
onDoubleTap
;
GestureDoubleTapCallback
onDoubleTap
;
Timer
_doubleTapTimer
;
Timer
_doubleTapTimer
;
_TapTracker
_firstTap
;
_TapTracker
_firstTap
;
final
Map
<
int
,
_TapTracker
>
_trackers
=
<
int
,
_TapTracker
>{};
final
Map
<
int
,
_TapTracker
>
_trackers
=
<
int
,
_TapTracker
>{};
@override
bool
isPointerAllowed
(
PointerEvent
event
)
{
if
(
_firstTap
==
null
)
{
switch
(
event
.
buttons
)
{
case
kPrimaryButton:
if
(
onDoubleTap
==
null
)
return
false
;
break
;
default
:
return
false
;
}
}
return
super
.
isPointerAllowed
(
event
);
}
@override
@override
void
addAllowedPointer
(
PointerEvent
event
)
{
void
addAllowedPointer
(
PointerEvent
event
)
{
if
(
_firstTap
!=
null
)
{
if
(
_firstTap
!=
null
)
{
if
(!
_firstTap
.
isWithinTolerance
(
event
,
kDoubleTapSlop
))
{
if
(!
_firstTap
.
isWithinTolerance
(
event
,
kDoubleTapSlop
))
{
// Ignore out-of-bounds second taps.
// Ignore out-of-bounds second taps.
return
;
return
;
}
else
if
(!
_firstTap
.
hasElapsedMinTime
()
||
!
_firstTap
.
hasSameButton
(
event
))
{
}
else
if
(!
_firstTap
.
hasElapsedMinTime
())
{
// Restart when the second tap is too close to the first, or when buttons
// Restart when the second tap is too close to the first.
// mismatch.
_reset
();
_reset
();
return
_trackFirstTap
(
event
);
return
addAllowedPointer
(
event
);
}
}
}
}
_trackFirstTap
(
event
);
}
void
_trackFirstTap
(
PointerEvent
event
)
{
_stopDoubleTapTimer
();
_stopDoubleTapTimer
();
final
_TapTracker
tracker
=
_TapTracker
(
final
_TapTracker
tracker
=
_TapTracker
(
event:
event
,
event:
event
,
...
@@ -277,7 +235,8 @@ class DoubleTapGestureRecognizer extends GestureRecognizer {
...
@@ -277,7 +235,8 @@ class DoubleTapGestureRecognizer extends GestureRecognizer {
tracker
.
entry
.
resolve
(
GestureDisposition
.
accepted
);
tracker
.
entry
.
resolve
(
GestureDisposition
.
accepted
);
_freezeTracker
(
tracker
);
_freezeTracker
(
tracker
);
_trackers
.
remove
(
tracker
.
pointer
);
_trackers
.
remove
(
tracker
.
pointer
);
_checkUp
(
tracker
.
initialButtons
);
if
(
onDoubleTap
!=
null
)
invokeCallback
<
void
>(
'onDoubleTap'
,
onDoubleTap
);
_reset
();
_reset
();
}
}
...
@@ -301,12 +260,6 @@ class DoubleTapGestureRecognizer extends GestureRecognizer {
...
@@ -301,12 +260,6 @@ class DoubleTapGestureRecognizer extends GestureRecognizer {
}
}
}
}
void
_checkUp
(
int
buttons
)
{
assert
(
buttons
==
kPrimaryButton
);
if
(
onDoubleTap
!=
null
)
invokeCallback
<
void
>(
'onDoubleTap'
,
onDoubleTap
);
}
@override
@override
String
get
debugDescription
=>
'double tap'
;
String
get
debugDescription
=>
'double tap'
;
}
}
...
...
packages/flutter/lib/src/gestures/tap.dart
View file @
60a1b2b9
...
@@ -9,7 +9,7 @@ import 'constants.dart';
...
@@ -9,7 +9,7 @@ import 'constants.dart';
import
'events.dart'
;
import
'events.dart'
;
import
'recognizer.dart'
;
import
'recognizer.dart'
;
/// Details for [GestureTapDownCallback], such as position
/// Details for [GestureTapDownCallback], such as position
.
///
///
/// See also:
/// See also:
///
///
...
@@ -45,6 +45,8 @@ typedef GestureTapDownCallback = void Function(TapDownDetails details);
...
@@ -45,6 +45,8 @@ typedef GestureTapDownCallback = void Function(TapDownDetails details);
/// * [GestureDetector.onTapUp], which receives this information.
/// * [GestureDetector.onTapUp], which receives this information.
/// * [TapGestureRecognizer], which passes this information to one of its callbacks.
/// * [TapGestureRecognizer], which passes this information to one of its callbacks.
class
TapUpDetails
{
class
TapUpDetails
{
/// Creates details for a [GestureTapUpCallback].
///
/// The [globalPosition] argument must not be null.
/// The [globalPosition] argument must not be null.
TapUpDetails
({
this
.
globalPosition
=
Offset
.
zero
})
TapUpDetails
({
this
.
globalPosition
=
Offset
.
zero
})
:
assert
(
globalPosition
!=
null
);
:
assert
(
globalPosition
!=
null
);
...
@@ -93,10 +95,14 @@ typedef GestureTapCancelCallback = void Function();
...
@@ -93,10 +95,14 @@ typedef GestureTapCancelCallback = void Function();
/// pointer interactions during a tap sequence are not recognized as additional
/// pointer interactions during a tap sequence are not recognized as additional
/// taps. For example, down-1, down-2, up-1, up-2 produces only one tap on up-1.
/// taps. For example, down-1, down-2, up-1, up-2 produces only one tap on up-1.
///
///
/// [TapGestureRecognizer] competes on pointer events of [kPrimaryButton] only
/// The lifecycle of events for a tap gesture is as follows:
/// when it has at least one non-null `onTap*` callback, and events of
///
/// [kSecondaryButton] only when it has at least one non-null `onSecondaryTap*`
/// * [onTapDown], which triggers after a short timeout ([deadline]) even if the
/// callback. If it has no callbacks, it is a no-op.
/// gesture has not won its arena yet.
/// * [onTapUp] and [onTap], which trigger when the pointer is released if the
/// gesture wins the arena.
/// * [onTapCancel], which triggers instead of [onTapUp] and [onTap] in the case
/// of the gesture not winning the arena.
///
///
/// See also:
/// See also:
///
///
...
@@ -106,25 +112,22 @@ class TapGestureRecognizer extends PrimaryPointerGestureRecognizer {
...
@@ -106,25 +112,22 @@ class TapGestureRecognizer extends PrimaryPointerGestureRecognizer {
/// Creates a tap gesture recognizer.
/// Creates a tap gesture recognizer.
TapGestureRecognizer
({
Object
debugOwner
})
:
super
(
deadline:
kPressTimeout
,
debugOwner:
debugOwner
);
TapGestureRecognizer
({
Object
debugOwner
})
:
super
(
deadline:
kPressTimeout
,
debugOwner:
debugOwner
);
/// A pointer that might cause a tap
of a primary button has contacted the
/// A pointer that might cause a tap
has contacted the screen at a particular
///
screen at a particular
location.
/// location.
///
///
/// This triggers
once a short timeout ([deadline]) has elapsed, or once
/// This triggers
before the gesture has won the arena, after a short timeout
///
the gestures has won the arena, whichever comes first
.
///
([deadline])
.
///
///
/// If the gesture doesn't win the arena, [onTapCancel] is called next.
/// If the gesture doesn't win the arena, [onTapCancel] is called next.
/// Otherwise, [onTapUp] is called next.
/// Otherwise, [onTapUp] is called next.
///
///
/// See also:
/// See also:
///
///
/// * [kPrimaryButton], the button this callback responds to.
/// * [onSecondaryTapDown], a similar callback but for a secondary button.
/// * [TapDownDetails], which is passed as an argument to this callback.
/// * [GestureDetector.onTapDown], which exposes this callback.
/// * [GestureDetector.onTapDown], which exposes this callback.
GestureTapDownCallback
onTapDown
;
GestureTapDownCallback
onTapDown
;
/// A pointer that will trigger a tap
of a primary button has stopped
/// A pointer that will trigger a tap
has stopped contacting the screen at a
///
contacting the screen at a
particular location.
/// particular location.
///
///
/// This triggers once the gesture has won the arena, immediately before
/// This triggers once the gesture has won the arena, immediately before
/// [onTap].
/// [onTap].
...
@@ -133,13 +136,11 @@ class TapGestureRecognizer extends PrimaryPointerGestureRecognizer {
...
@@ -133,13 +136,11 @@ class TapGestureRecognizer extends PrimaryPointerGestureRecognizer {
///
///
/// See also:
/// See also:
///
///
/// * [kPrimaryButton], the button this callback responds to.
/// * [onSecondaryTapUp], a similar callback but for a secondary button.
/// * [TapUpDetails], which is passed as an argument to this callback.
/// * [GestureDetector.onTapUp], which exposes this callback.
/// * [GestureDetector.onTapUp], which exposes this callback.
/// * [TapUpDetails], which is passed as an argument to this callback.
GestureTapUpCallback
onTapUp
;
GestureTapUpCallback
onTapUp
;
/// A tap
of a primary button
has occurred.
/// A tap has occurred.
///
///
/// This triggers once the gesture has won the arena, immediately after
/// This triggers once the gesture has won the arena, immediately after
/// [onTapUp].
/// [onTapUp].
...
@@ -148,8 +149,6 @@ class TapGestureRecognizer extends PrimaryPointerGestureRecognizer {
...
@@ -148,8 +149,6 @@ class TapGestureRecognizer extends PrimaryPointerGestureRecognizer {
///
///
/// See also:
/// See also:
///
///
/// * [kPrimaryButton], the button this callback responds to.
/// * [onTapUp], which has the same timing but with details.
/// * [GestureDetector.onTap], which exposes this callback.
/// * [GestureDetector.onTap], which exposes this callback.
GestureTapCallback
onTap
;
GestureTapCallback
onTap
;
...
@@ -162,121 +161,37 @@ class TapGestureRecognizer extends PrimaryPointerGestureRecognizer {
...
@@ -162,121 +161,37 @@ class TapGestureRecognizer extends PrimaryPointerGestureRecognizer {
///
///
/// See also:
/// See also:
///
///
/// * [kPrimaryButton], the button this callback responds to.
/// * [onSecondaryTapCancel], a similar callback but for a secondary button.
/// * [GestureDetector.onTapCancel], which exposes this callback.
/// * [GestureDetector.onTapCancel], which exposes this callback.
GestureTapCancelCallback
onTapCancel
;
GestureTapCancelCallback
onTapCancel
;
/// A pointer that might cause a tap of a secondary button has contacted the
/// screen at a particular location.
///
/// This triggers once a short timeout ([deadline]) has elapsed, or once
/// the gestures has won the arena, whichever comes first.
///
/// If the gesture doesn't win the arena, [onSecondaryTapCancel] is called next.
/// Otherwise, [onSecondaryTapUp] is called next.
///
/// See also:
///
/// * [kSecondaryButton], the button this callback responds to.
/// * [onPrimaryTapDown], a similar callback but for a primary button.
/// * [TapDownDetails], which is passed as an argument to this callback.
/// * [GestureDetector.onSecondaryTapDown], which exposes this callback.
GestureTapDownCallback
onSecondaryTapDown
;
/// A pointer that will trigger a tap of a secondary button has stopped
/// contacting the screen at a particular location.
///
/// This triggers once the gesture has won the arena.
///
/// If the gesture doesn't win the arena, [onSecondaryTapCancel] is called
/// instead.
///
/// See also:
///
/// * [kSecondaryButton], the button this callback responds to.
/// * [onPrimaryTapUp], a similar callback but for a primary button.
/// * [TapUpDetails], which is passed as an argument to this callback.
/// * [GestureDetector.onSecondaryTapUp], which exposes this callback.
GestureTapUpCallback
onSecondaryTapUp
;
/// The pointer that previously triggered [onSecondaryTapDown] will not end up
/// causing a tap.
///
/// This triggers if the gesture loses the arena.
///
/// If the gesture wins the arena, [onSecondaryTapUp] is called instead.
///
/// See also:
///
/// * [kSecondaryButton], the button this callback responds to.
/// * [onPrimaryTapCancel], a similar callback but for a primary button.
/// * [GestureDetector.onTapCancel], which exposes this callback.
GestureTapCancelCallback
onSecondaryTapCancel
;
bool
_sentTapDown
=
false
;
bool
_sentTapDown
=
false
;
bool
_wonArenaForPrimaryPointer
=
false
;
bool
_wonArenaForPrimaryPointer
=
false
;
Offset
_finalPosition
;
Offset
_finalPosition
;
// The buttons sent by `PointerDownEvent`. If a `PointerMoveEvent` comes with a
// different set of buttons, the gesture is canceled.
int
_initialButtons
;
@override
bool
isPointerAllowed
(
PointerDownEvent
event
)
{
switch
(
event
.
buttons
)
{
case
kPrimaryButton:
if
(
onTapDown
==
null
&&
onTap
==
null
&&
onTapUp
==
null
&&
onTapCancel
==
null
)
return
false
;
break
;
case
kSecondaryButton:
if
(
onSecondaryTapDown
==
null
&&
onSecondaryTapUp
==
null
&&
onSecondaryTapCancel
==
null
)
return
false
;
break
;
default
:
return
false
;
}
return
super
.
isPointerAllowed
(
event
);
}
@override
void
addAllowedPointer
(
PointerDownEvent
event
)
{
super
.
addAllowedPointer
(
event
);
// `_initialButtons` must be assigned here instead of `handlePrimaryPointer`,
// because `acceptGesture` might be called before `handlePrimaryPointer`,
// which relies on `_initialButtons` to create `TapDownDetails`.
_initialButtons
=
event
.
buttons
;
}
@override
@override
void
handlePrimaryPointer
(
PointerEvent
event
)
{
void
handlePrimaryPointer
(
PointerEvent
event
)
{
if
(
event
is
PointerUpEvent
)
{
if
(
event
is
PointerUpEvent
)
{
_finalPosition
=
event
.
position
;
_finalPosition
=
event
.
position
;
_checkUp
();
if
(
_wonArenaForPrimaryPointer
)
{
resolve
(
GestureDisposition
.
accepted
);
_checkUp
();
}
}
else
if
(
event
is
PointerCancelEvent
)
{
}
else
if
(
event
is
PointerCancelEvent
)
{
resolve
(
GestureDisposition
.
rejected
);
if
(
_sentTapDown
&&
onTapCancel
!=
null
)
{
if
(
_sentTapDown
)
{
invokeCallback
<
void
>(
'onTapCancel'
,
onTapCancel
);
_checkCancel
(
''
);
}
}
_reset
();
_reset
();
}
else
if
(
event
.
buttons
!=
_initialButtons
)
{
resolve
(
GestureDisposition
.
rejected
);
stopTrackingPointer
(
primaryPointer
);
}
}
}
}
@override
@override
void
resolve
(
GestureDisposition
disposition
)
{
void
resolve
(
GestureDisposition
disposition
)
{
if
(
_wonArenaForPrimaryPointer
&&
disposition
==
GestureDisposition
.
rejected
)
{
if
(
_wonArenaForPrimaryPointer
&&
disposition
==
GestureDisposition
.
rejected
)
{
// This can happen if the gesture has been canceled. For example, when
// This can happen if the superclass decides the primary pointer
// the pointer has exceeded the touch slop, the buttons have been changed,
// exceeded the touch slop, or if the recognizer is disposed.
// or if the recognizer is disposed.
assert
(
_sentTapDown
);
assert
(
_sentTapDown
);
_checkCancel
(
'spontaneous '
);
if
(
onTapCancel
!=
null
)
invokeCallback
<
void
>(
'spontaneous onTapCancel'
,
onTapCancel
);
_reset
();
_reset
();
}
}
super
.
resolve
(
disposition
);
super
.
resolve
(
disposition
);
...
@@ -303,70 +218,27 @@ class TapGestureRecognizer extends PrimaryPointerGestureRecognizer {
...
@@ -303,70 +218,27 @@ class TapGestureRecognizer extends PrimaryPointerGestureRecognizer {
if
(
pointer
==
primaryPointer
)
{
if
(
pointer
==
primaryPointer
)
{
// Another gesture won the arena.
// Another gesture won the arena.
assert
(
state
!=
GestureRecognizerState
.
possible
);
assert
(
state
!=
GestureRecognizerState
.
possible
);
if
(
_sentTapDown
)
if
(
_sentTapDown
&&
onTapCancel
!=
null
)
_checkCancel
(
'forced '
);
invokeCallback
<
void
>(
'forced onTapCancel'
,
onTapCancel
);
_reset
();
_reset
();
}
}
}
}
void
_checkDown
()
{
void
_checkDown
()
{
if
(
_sentTapDown
)
{
if
(!
_sentTapDown
)
{
return
;
if
(
onTapDown
!=
null
)
}
invokeCallback
<
void
>(
'onTapDown'
,
()
{
onTapDown
(
TapDownDetails
(
globalPosition:
initialPosition
));
});
final
TapDownDetails
details
=
TapDownDetails
(
_sentTapDown
=
true
;
globalPosition:
initialPosition
,
);
switch
(
_initialButtons
)
{
case
kPrimaryButton:
if
(
onTapDown
!=
null
)
invokeCallback
<
void
>(
'onTapDown'
,
()
=>
onTapDown
(
details
));
break
;
case
kSecondaryButton:
if
(
onSecondaryTapDown
!=
null
)
invokeCallback
<
void
>(
'onSecondaryTapDown'
,
()
=>
onSecondaryTapDown
(
details
));
break
;
default
:
}
}
_sentTapDown
=
true
;
}
}
void
_checkUp
()
{
void
_checkUp
()
{
if
(!
_wonArenaForPrimaryPointer
||
_finalPosition
==
null
)
{
if
(
_finalPosition
!=
null
)
{
return
;
if
(
onTapUp
!=
null
)
}
invokeCallback
<
void
>(
'onTapUp'
,
()
{
onTapUp
(
TapUpDetails
(
globalPosition:
_finalPosition
));
});
final
TapUpDetails
details
=
TapUpDetails
(
if
(
onTap
!=
null
)
globalPosition:
_finalPosition
,
invokeCallback
<
void
>(
'onTap'
,
onTap
);
);
_reset
();
switch
(
_initialButtons
)
{
case
kPrimaryButton:
if
(
onTapUp
!=
null
)
invokeCallback
<
void
>(
'onTapUp'
,
()
=>
onTapUp
(
details
));
if
(
onTap
!=
null
)
invokeCallback
<
void
>(
'onTap'
,
onTap
);
break
;
case
kSecondaryButton:
if
(
onSecondaryTapUp
!=
null
)
invokeCallback
<
void
>(
'onSecondaryTapUp'
,
()
=>
onSecondaryTapUp
(
details
));
break
;
default
:
}
_reset
();
}
void
_checkCancel
(
String
note
)
{
switch
(
_initialButtons
)
{
case
kPrimaryButton:
if
(
onTapCancel
!=
null
)
invokeCallback
<
void
>(
'
${note}
onTapCancel'
,
onTapCancel
);
break
;
case
kSecondaryButton:
if
(
onSecondaryTapCancel
!=
null
)
invokeCallback
<
void
>(
'
${note}
onSecondaryTapCancel'
,
onSecondaryTapCancel
);
break
;
default
:
}
}
}
}
...
@@ -374,7 +246,6 @@ class TapGestureRecognizer extends PrimaryPointerGestureRecognizer {
...
@@ -374,7 +246,6 @@ class TapGestureRecognizer extends PrimaryPointerGestureRecognizer {
_sentTapDown
=
false
;
_sentTapDown
=
false
;
_wonArenaForPrimaryPointer
=
false
;
_wonArenaForPrimaryPointer
=
false
;
_finalPosition
=
null
;
_finalPosition
=
null
;
_initialButtons
=
null
;
}
}
@override
@override
...
@@ -386,6 +257,5 @@ class TapGestureRecognizer extends PrimaryPointerGestureRecognizer {
...
@@ -386,6 +257,5 @@ class TapGestureRecognizer extends PrimaryPointerGestureRecognizer {
properties
.
add
(
FlagProperty
(
'wonArenaForPrimaryPointer'
,
value:
_wonArenaForPrimaryPointer
,
ifTrue:
'won arena'
));
properties
.
add
(
FlagProperty
(
'wonArenaForPrimaryPointer'
,
value:
_wonArenaForPrimaryPointer
,
ifTrue:
'won arena'
));
properties
.
add
(
DiagnosticsProperty
<
Offset
>(
'finalPosition'
,
_finalPosition
,
defaultValue:
null
));
properties
.
add
(
DiagnosticsProperty
<
Offset
>(
'finalPosition'
,
_finalPosition
,
defaultValue:
null
));
properties
.
add
(
FlagProperty
(
'sentTapDown'
,
value:
_sentTapDown
,
ifTrue:
'sent tap down'
));
properties
.
add
(
FlagProperty
(
'sentTapDown'
,
value:
_sentTapDown
,
ifTrue:
'sent tap down'
));
// TODO(tongmu): Add property _initialButtons and update related tests
}
}
}
}
packages/flutter/lib/src/widgets/gesture_detector.dart
View file @
60a1b2b9
...
@@ -166,9 +166,6 @@ class GestureDetector extends StatelessWidget {
...
@@ -166,9 +166,6 @@ class GestureDetector extends StatelessWidget {
this
.
onTapUp
,
this
.
onTapUp
,
this
.
onTap
,
this
.
onTap
,
this
.
onTapCancel
,
this
.
onTapCancel
,
this
.
onSecondaryTapDown
,
this
.
onSecondaryTapUp
,
this
.
onSecondaryTapCancel
,
this
.
onDoubleTap
,
this
.
onDoubleTap
,
this
.
onLongPress
,
this
.
onLongPress
,
this
.
onLongPressStart
,
this
.
onLongPressStart
,
...
@@ -232,37 +229,28 @@ class GestureDetector extends StatelessWidget {
...
@@ -232,37 +229,28 @@ class GestureDetector extends StatelessWidget {
/// {@macro flutter.widgets.child}
/// {@macro flutter.widgets.child}
final
Widget
child
;
final
Widget
child
;
/// A pointer that might cause a tap
with a primary button has contacted the
/// A pointer that might cause a tap
has contacted the screen at a particular
///
screen at a particular
location.
/// location.
///
///
/// This is called after a short timeout, even if the winning gesture has not
/// This is called after a short timeout, even if the winning gesture has not
/// yet been selected. If the tap gesture wins, [onTapUp] will be called,
/// yet been selected. If the tap gesture wins, [onTapUp] will be called,
/// otherwise [onTapCancel] will be called.
/// otherwise [onTapCancel] will be called.
///
/// See also:
///
/// * [kPrimaryButton], the button this callback responds to.
final
GestureTapDownCallback
onTapDown
;
final
GestureTapDownCallback
onTapDown
;
/// A pointer that will trigger a tap
with a primary button has stopped
/// A pointer that will trigger a tap
has stopped contacting the screen at a
///
contacting the screen at a
particular location.
/// particular location.
///
///
/// This triggers immediately before [onTap] in the case of the tap gesture
/// This triggers immediately before [onTap] in the case of the tap gesture
/// winning. If the tap gesture did not win, [onTapCancel] is called instead.
/// winning. If the tap gesture did not win, [onTapCancel] is called instead.
///
/// See also:
///
/// * [kPrimaryButton], the button this callback responds to.
final
GestureTapUpCallback
onTapUp
;
final
GestureTapUpCallback
onTapUp
;
/// A tap
with a primary button
has occurred.
/// A tap has occurred.
///
///
/// This triggers when the tap gesture wins. If the tap gesture did not win,
/// This triggers when the tap gesture wins. If the tap gesture did not win,
/// [onTapCancel] is called instead.
/// [onTapCancel] is called instead.
///
///
/// See also:
/// See also:
///
///
/// * [kPrimaryButton], the button this callback responds to.
/// * [onTapUp], which is called at the same time but includes details
/// * [onTapUp], which is called at the same time but includes details
/// regarding the pointer position.
/// regarding the pointer position.
final
GestureTapCallback
onTap
;
final
GestureTapCallback
onTap
;
...
@@ -272,222 +260,104 @@ class GestureDetector extends StatelessWidget {
...
@@ -272,222 +260,104 @@ class GestureDetector extends StatelessWidget {
///
///
/// This is called after [onTapDown], and instead of [onTapUp] and [onTap], if
/// This is called after [onTapDown], and instead of [onTapUp] and [onTap], if
/// the tap gesture did not win.
/// the tap gesture did not win.
///
/// See also:
///
/// * [kPrimaryButton], the button this callback responds to.
final
GestureTapCancelCallback
onTapCancel
;
final
GestureTapCancelCallback
onTapCancel
;
/// A pointer that might cause a tap with a secondary button has contacted the
/// The user has tapped the screen at the same location twice in quick
/// screen at a particular location.
/// succession.
///
/// This is called after a short timeout, even if the winning gesture has not
/// yet been selected. If the tap gesture wins, [onSecondaryTapUp] will be
/// called, otherwise [onSecondaryTapCancel] will be called.
///
/// See also:
///
/// * [kSecondaryButton], the button this callback responds to.
final
GestureTapDownCallback
onSecondaryTapDown
;
/// A pointer that will trigger a tap with a secondary button has stopped
/// contacting the screen at a particular location.
///
/// This triggers in the case of the tap gesture winning. If the tap gesture
/// did not win, [onSecondaryTapCancel] is called instead.
///
/// See also:
///
/// * [kSecondaryButton], the button this callback responds to.
final
GestureTapUpCallback
onSecondaryTapUp
;
/// The pointer that previously triggered [onSecondaryTapDown] will not end up
/// causing a tap.
///
/// This is called after [onSecondaryTapDown], and instead of
/// [onSecondaryTapUp], if the tap gesture did not win.
///
/// See also:
///
/// * [kSecondaryButton], the button this callback responds to.
final
GestureTapCancelCallback
onSecondaryTapCancel
;
/// The user has tapped the screen with a primary button at the same location
/// twice in quick succession.
///
/// See also:
///
/// * [kPrimaryButton], the button this callback responds to.
final
GestureTapCallback
onDoubleTap
;
final
GestureTapCallback
onDoubleTap
;
/// Called when a long press gesture
with a primary button
has been recognized.
/// Called when a long press gesture has been recognized.
///
///
/// Triggered when a pointer has remained in contact with the screen at the
/// Triggered when a pointer has remained in contact with the screen at the
/// same location for a long period of time.
/// same location for a long period of time.
///
///
/// See also:
/// See also:
///
///
/// * [
kPrimaryButton], the button this callback responds to.
/// * [
onLongPressStart], which has the same timing but has data for the
///
* [onLongPressStart], which has the same timing but has gesture details
.
///
press location
.
final
GestureLongPressCallback
onLongPress
;
final
GestureLongPressCallback
onLongPress
;
/// Call
ed when a long press gesture with a primary button has been recognized
.
/// Call
back for long press start with gesture location
.
///
///
/// Triggered when a pointer has remained in contact with the screen at the
/// Triggered when a pointer has remained in contact with the screen at the
/// same location for a long period of time.
/// same location for a long period of time.
///
///
/// See also:
/// See also:
///
///
/// * [kPrimaryButton], the button this callback responds to.
/// * [onLongPress], which has the same timing but without the location data.
/// * [onLongPress], which has the same timing but without the gesture details.
final
GestureLongPressStartCallback
onLongPressStart
;
final
GestureLongPressStartCallback
onLongPressStart
;
/// A pointer has been drag-moved after a long press with a primary button.
/// A pointer has been drag-moved after a long press.
///
/// See also:
///
/// * [kPrimaryButton], the button this callback responds to.
final
GestureLongPressMoveUpdateCallback
onLongPressMoveUpdate
;
final
GestureLongPressMoveUpdateCallback
onLongPressMoveUpdate
;
/// A pointer that has triggered a long-press with a primary button has
/// A pointer that has triggered a long-press has stopped contacting the screen.
/// stopped contacting the screen.
///
///
/// See also:
/// See also:
///
///
/// * [
kPrimaryButton], the button this callback responds to.
/// * [
onLongPressEnd], which has the same timing but has data for the up
///
* [onLongPressEnd], which has the same timing but has gesture details
.
///
gesture location
.
final
GestureLongPressUpCallback
onLongPressUp
;
final
GestureLongPressUpCallback
onLongPressUp
;
/// A pointer that has triggered a long-press with a primary button has
/// A pointer that has triggered a long-press has stopped contacting the screen.
/// stopped contacting the screen.
///
///
/// See also:
/// See also:
///
///
/// * [kPrimaryButton], the button this callback responds to.
/// * [onLongPressUp], which has the same timing but without the location data.
/// * [onLongPressUp], which has the same timing but without the gesture
/// details.
final
GestureLongPressEndCallback
onLongPressEnd
;
final
GestureLongPressEndCallback
onLongPressEnd
;
/// A pointer has contacted the screen with a primary button and might begin
/// A pointer has contacted the screen and might begin to move vertically.
/// to move vertically.
///
/// See also:
///
/// * [kPrimaryButton], the button this callback responds to.
final
GestureDragDownCallback
onVerticalDragDown
;
final
GestureDragDownCallback
onVerticalDragDown
;
/// A pointer has contacted the screen with a primary button and has begun to
/// A pointer has contacted the screen and has begun to move vertically.
/// move vertically.
///
/// See also:
///
/// * [kPrimaryButton], the button this callback responds to.
final
GestureDragStartCallback
onVerticalDragStart
;
final
GestureDragStartCallback
onVerticalDragStart
;
/// A pointer that is in contact with the screen with a primary button and
/// A pointer that is in contact with the screen and moving vertically has
/// moving vertically has moved in the vertical direction.
/// moved in the vertical direction.
///
/// See also:
///
/// * [kPrimaryButton], the button this callback responds to.
final
GestureDragUpdateCallback
onVerticalDragUpdate
;
final
GestureDragUpdateCallback
onVerticalDragUpdate
;
/// A pointer that was previously in contact with the screen with a primary
/// A pointer that was previously in contact with the screen and moving
/// button and moving vertically is no longer in contact with the screen and
/// vertically is no longer in contact with the screen and was moving at a
/// was moving at a specific velocity when it stopped contacting the screen.
/// specific velocity when it stopped contacting the screen.
///
/// See also:
///
/// * [kPrimaryButton], the button this callback responds to.
final
GestureDragEndCallback
onVerticalDragEnd
;
final
GestureDragEndCallback
onVerticalDragEnd
;
/// The pointer that previously triggered [onVerticalDragDown] did not
/// The pointer that previously triggered [onVerticalDragDown] did not
/// complete.
/// complete.
///
/// See also:
///
/// * [kPrimaryButton], the button this callback responds to.
final
GestureDragCancelCallback
onVerticalDragCancel
;
final
GestureDragCancelCallback
onVerticalDragCancel
;
/// A pointer has contacted the screen with a primary button and might begin
/// A pointer has contacted the screen and might begin to move horizontally.
/// to move horizontally.
///
/// See also:
///
/// * [kPrimaryButton], the button this callback responds to.
final
GestureDragDownCallback
onHorizontalDragDown
;
final
GestureDragDownCallback
onHorizontalDragDown
;
/// A pointer has contacted the screen with a primary button and has begun to
/// A pointer has contacted the screen and has begun to move horizontally.
/// move horizontally.
///
/// See also:
///
/// * [kPrimaryButton], the button this callback responds to.
final
GestureDragStartCallback
onHorizontalDragStart
;
final
GestureDragStartCallback
onHorizontalDragStart
;
/// A pointer that is in contact with the screen with a primary button and
/// A pointer that is in contact with the screen and moving horizontally has
/// moving horizontally has moved in the horizontal direction.
/// moved in the horizontal direction.
///
/// See also:
///
/// * [kPrimaryButton], the button this callback responds to.
final
GestureDragUpdateCallback
onHorizontalDragUpdate
;
final
GestureDragUpdateCallback
onHorizontalDragUpdate
;
/// A pointer that was previously in contact with the screen with a primary
/// A pointer that was previously in contact with the screen and moving
/// button and moving horizontally is no longer in contact with the screen and
/// horizontally is no longer in contact with the screen and was moving at a
/// was moving at a specific velocity when it stopped contacting the screen.
/// specific velocity when it stopped contacting the screen.
///
/// See also:
///
/// * [kPrimaryButton], the button this callback responds to.
final
GestureDragEndCallback
onHorizontalDragEnd
;
final
GestureDragEndCallback
onHorizontalDragEnd
;
/// The pointer that previously triggered [onHorizontalDragDown] did not
/// The pointer that previously triggered [onHorizontalDragDown] did not
/// complete.
/// complete.
///
/// See also:
///
/// * [kPrimaryButton], the button this callback responds to.
final
GestureDragCancelCallback
onHorizontalDragCancel
;
final
GestureDragCancelCallback
onHorizontalDragCancel
;
/// A pointer has contacted the screen with a primary button and might begin
/// A pointer has contacted the screen and might begin to move.
/// to move.
///
/// See also:
///
/// * [kPrimaryButton], the button this callback responds to.
final
GestureDragDownCallback
onPanDown
;
final
GestureDragDownCallback
onPanDown
;
/// A pointer has contacted the screen with a primary button and has begun to
/// A pointer has contacted the screen and has begun to move.
/// move.
///
/// See also:
///
/// * [kPrimaryButton], the button this callback responds to.
final
GestureDragStartCallback
onPanStart
;
final
GestureDragStartCallback
onPanStart
;
/// A pointer that is in contact with the screen with a primary button and
/// A pointer that is in contact with the screen and moving has moved again.
/// moving has moved again.
///
/// See also:
///
/// * [kPrimaryButton], the button this callback responds to.
final
GestureDragUpdateCallback
onPanUpdate
;
final
GestureDragUpdateCallback
onPanUpdate
;
/// A pointer that was previously in contact with the screen with a primary
/// A pointer that was previously in contact with the screen and moving
/// button and moving is no longer in contact with the screen and was moving
/// is no longer in contact with the screen and was moving at a specific
/// at a specific velocity when it stopped contacting the screen.
/// velocity when it stopped contacting the screen.
///
/// See also:
///
/// * [kPrimaryButton], the button this callback responds to.
final
GestureDragEndCallback
onPanEnd
;
final
GestureDragEndCallback
onPanEnd
;
/// The pointer that previously triggered [onPanDown] did not complete.
/// The pointer that previously triggered [onPanDown] did not complete.
///
/// See also:
///
/// * [kPrimaryButton], the button this callback responds to.
final
GestureDragCancelCallback
onPanCancel
;
final
GestureDragCancelCallback
onPanCancel
;
/// The pointers in contact with the screen have established a focal point and
/// The pointers in contact with the screen have established a focal point and
...
@@ -570,15 +440,7 @@ class GestureDetector extends StatelessWidget {
...
@@ -570,15 +440,7 @@ class GestureDetector extends StatelessWidget {
Widget
build
(
BuildContext
context
)
{
Widget
build
(
BuildContext
context
)
{
final
Map
<
Type
,
GestureRecognizerFactory
>
gestures
=
<
Type
,
GestureRecognizerFactory
>{};
final
Map
<
Type
,
GestureRecognizerFactory
>
gestures
=
<
Type
,
GestureRecognizerFactory
>{};
if
(
if
(
onTapDown
!=
null
||
onTapUp
!=
null
||
onTap
!=
null
||
onTapCancel
!=
null
)
{
onTapDown
!=
null
||
onTapUp
!=
null
||
onTap
!=
null
||
onTapCancel
!=
null
||
onSecondaryTapDown
!=
null
||
onSecondaryTapUp
!=
null
||
onSecondaryTapCancel
!=
null
)
{
gestures
[
TapGestureRecognizer
]
=
GestureRecognizerFactoryWithHandlers
<
TapGestureRecognizer
>(
gestures
[
TapGestureRecognizer
]
=
GestureRecognizerFactoryWithHandlers
<
TapGestureRecognizer
>(
()
=>
TapGestureRecognizer
(
debugOwner:
this
),
()
=>
TapGestureRecognizer
(
debugOwner:
this
),
(
TapGestureRecognizer
instance
)
{
(
TapGestureRecognizer
instance
)
{
...
@@ -586,10 +448,7 @@ class GestureDetector extends StatelessWidget {
...
@@ -586,10 +448,7 @@ class GestureDetector extends StatelessWidget {
..
onTapDown
=
onTapDown
..
onTapDown
=
onTapDown
..
onTapUp
=
onTapUp
..
onTapUp
=
onTapUp
..
onTap
=
onTap
..
onTap
=
onTap
..
onTapCancel
=
onTapCancel
..
onTapCancel
=
onTapCancel
;
..
onSecondaryTapDown
=
onSecondaryTapDown
..
onSecondaryTapUp
=
onSecondaryTapUp
..
onSecondaryTapCancel
=
onSecondaryTapCancel
;
},
},
);
);
}
}
...
@@ -938,14 +797,8 @@ class RawGestureDetectorState extends State<RawGestureDetector> {
...
@@ -938,14 +797,8 @@ class RawGestureDetectorState extends State<RawGestureDetector> {
void
_handleSemanticsLongPress
()
{
void
_handleSemanticsLongPress
()
{
final
LongPressGestureRecognizer
recognizer
=
_recognizers
[
LongPressGestureRecognizer
];
final
LongPressGestureRecognizer
recognizer
=
_recognizers
[
LongPressGestureRecognizer
];
assert
(
recognizer
!=
null
);
assert
(
recognizer
!=
null
);
if
(
recognizer
.
onLongPressStart
!=
null
)
recognizer
.
onLongPressStart
(
const
LongPressStartDetails
());
if
(
recognizer
.
onLongPress
!=
null
)
if
(
recognizer
.
onLongPress
!=
null
)
recognizer
.
onLongPress
();
recognizer
.
onLongPress
();
if
(
recognizer
.
onLongPressEnd
!=
null
)
recognizer
.
onLongPressEnd
(
const
LongPressEndDetails
());
if
(
recognizer
.
onLongPressUp
!=
null
)
recognizer
.
onLongPressUp
();
}
}
void
_handleSemanticsHorizontalDragUpdate
(
DragUpdateDetails
updateDetails
)
{
void
_handleSemanticsHorizontalDragUpdate
(
DragUpdateDetails
updateDetails
)
{
...
...
packages/flutter/test/gestures/debug_test.dart
View file @
60a1b2b9
...
@@ -147,8 +147,7 @@ void main() {
...
@@ -147,8 +147,7 @@ void main() {
});
});
test
(
'TapGestureRecognizer _sentTapDown toString'
,
()
{
test
(
'TapGestureRecognizer _sentTapDown toString'
,
()
{
final
TapGestureRecognizer
tap
=
TapGestureRecognizer
()
final
TapGestureRecognizer
tap
=
TapGestureRecognizer
();
..
onTap
=
()
{};
// Add a callback so that event can be added
expect
(
tap
.
toString
(),
equalsIgnoringHashCodes
(
'TapGestureRecognizer#00000(state: ready)'
));
expect
(
tap
.
toString
(),
equalsIgnoringHashCodes
(
'TapGestureRecognizer#00000(state: ready)'
));
const
PointerEvent
event
=
PointerDownEvent
(
pointer:
1
,
position:
Offset
(
10.0
,
10.0
));
const
PointerEvent
event
=
PointerDownEvent
(
pointer:
1
,
position:
Offset
(
10.0
,
10.0
));
tap
.
addPointer
(
event
);
tap
.
addPointer
(
event
);
...
...
packages/flutter/test/gestures/double_tap_test.dart
View file @
60a1b2b9
...
@@ -75,7 +75,7 @@ void main() {
...
@@ -75,7 +75,7 @@ void main() {
position:
Offset
(
25.0
,
25.0
),
position:
Offset
(
25.0
,
25.0
),
);
);
// Down/up pair 5: normal tap sequence identical to pair 1
// Down/up pair 5: normal tap sequence identical to pair 1
with different pointer
const
PointerDownEvent
down5
=
PointerDownEvent
(
const
PointerDownEvent
down5
=
PointerDownEvent
(
pointer:
5
,
pointer:
5
,
position:
Offset
(
10.0
,
10.0
),
position:
Offset
(
10.0
,
10.0
),
...
@@ -86,18 +86,6 @@ void main() {
...
@@ -86,18 +86,6 @@ void main() {
position:
Offset
(
11.0
,
9.0
),
position:
Offset
(
11.0
,
9.0
),
);
);
// Down/up pair 6: normal tap sequence close to pair 1 but on secondary button
const
PointerDownEvent
down6
=
PointerDownEvent
(
pointer:
6
,
position:
Offset
(
10.0
,
10.0
),
buttons:
kSecondaryMouseButton
,
);
const
PointerUpEvent
up6
=
PointerUpEvent
(
pointer:
6
,
position:
Offset
(
11.0
,
9.0
),
);
testGesture
(
'Should recognize double tap'
,
(
GestureTester
tester
)
{
testGesture
(
'Should recognize double tap'
,
(
GestureTester
tester
)
{
final
DoubleTapGestureRecognizer
tap
=
DoubleTapGestureRecognizer
();
final
DoubleTapGestureRecognizer
tap
=
DoubleTapGestureRecognizer
();
...
@@ -618,183 +606,4 @@ void main() {
...
@@ -618,183 +606,4 @@ void main() {
tap
.
dispose
();
tap
.
dispose
();
});
});
group
(
'Enforce consistent-button restriction:'
,
()
{
testGesture
(
'Button change should interrupt existing sequence'
,
(
GestureTester
tester
)
{
// Down1 -> down6 (different button from 1) -> down2 (same button as 1)
// Down1 and down2 could've been a double tap, but is interrupted by down 6.
const
Duration
interval
=
Duration
(
milliseconds:
100
);
assert
(
interval
*
2
<
kDoubleTapTimeout
);
assert
(
interval
>
kDoubleTapMinTime
);
final
DoubleTapGestureRecognizer
tap
=
DoubleTapGestureRecognizer
();
bool
doubleTapRecognized
=
false
;
tap
.
onDoubleTap
=
()
{
doubleTapRecognized
=
true
;
};
tap
.
addPointer
(
down1
);
tester
.
closeArena
(
1
);
tester
.
route
(
down1
);
tester
.
route
(
up1
);
GestureBinding
.
instance
.
gestureArena
.
sweep
(
1
);
tester
.
async
.
elapse
(
interval
);
tap
.
addPointer
(
down6
);
tester
.
closeArena
(
6
);
tester
.
route
(
down6
);
tester
.
route
(
up6
);
GestureBinding
.
instance
.
gestureArena
.
sweep
(
6
);
tester
.
async
.
elapse
(
interval
);
expect
(
doubleTapRecognized
,
isFalse
);
tap
.
addPointer
(
down2
);
tester
.
closeArena
(
2
);
tester
.
route
(
down2
);
tester
.
route
(
up2
);
GestureBinding
.
instance
.
gestureArena
.
sweep
(
2
);
expect
(
doubleTapRecognized
,
isFalse
);
tap
.
dispose
();
});
testGesture
(
'Button change should start a valid sequence'
,
(
GestureTester
tester
)
{
// Down6 -> down1 (different button from 6) -> down2 (same button as 1)
const
Duration
interval
=
Duration
(
milliseconds:
100
);
assert
(
interval
*
2
<
kDoubleTapTimeout
);
assert
(
interval
>
kDoubleTapMinTime
);
final
DoubleTapGestureRecognizer
tap
=
DoubleTapGestureRecognizer
();
bool
doubleTapRecognized
=
false
;
tap
.
onDoubleTap
=
()
{
doubleTapRecognized
=
true
;
};
tap
.
addPointer
(
down6
);
tester
.
closeArena
(
6
);
tester
.
route
(
down6
);
tester
.
route
(
up6
);
GestureBinding
.
instance
.
gestureArena
.
sweep
(
6
);
tester
.
async
.
elapse
(
interval
);
tap
.
addPointer
(
down1
);
tester
.
closeArena
(
1
);
tester
.
route
(
down1
);
tester
.
route
(
up1
);
GestureBinding
.
instance
.
gestureArena
.
sweep
(
1
);
expect
(
doubleTapRecognized
,
isFalse
);
tester
.
async
.
elapse
(
interval
);
tap
.
addPointer
(
down2
);
tester
.
closeArena
(
2
);
tester
.
route
(
down2
);
tester
.
route
(
up2
);
GestureBinding
.
instance
.
gestureArena
.
sweep
(
2
);
expect
(
doubleTapRecognized
,
isTrue
);
tap
.
dispose
();
});
});
group
(
'Recognizers listening on different buttons do not form competition:'
,
()
{
// This test is assisted by tap recognizers. If a tap gesture has
// no competing recognizers, a pointer down event triggers its onTapDown
// immediately; if there are competitors, onTapDown is triggered after a
// timeout.
// The following tests make sure that double tap recognizers do not form
// competition with a tap gesture recognizer listening on a different button.
final
List
<
String
>
recognized
=
<
String
>[];
TapGestureRecognizer
tapPrimary
;
TapGestureRecognizer
tapSecondary
;
DoubleTapGestureRecognizer
doubleTap
;
setUp
(()
{
tapPrimary
=
TapGestureRecognizer
()
..
onTapDown
=
(
TapDownDetails
details
)
{
recognized
.
add
(
'tapPrimary'
);
};
tapSecondary
=
TapGestureRecognizer
()
..
onSecondaryTapDown
=
(
TapDownDetails
details
)
{
recognized
.
add
(
'tapSecondary'
);
};
doubleTap
=
DoubleTapGestureRecognizer
()
..
onDoubleTap
=
()
{
recognized
.
add
(
'doubleTap'
);
};
});
tearDown
(()
{
recognized
.
clear
();
tapPrimary
.
dispose
();
tapSecondary
.
dispose
();
doubleTap
.
dispose
();
});
testGesture
(
'A primary double tap recognizer does not form competion with a secondary tap recognizer'
,
(
GestureTester
tester
)
{
doubleTap
.
addPointer
(
down6
);
tapSecondary
.
addPointer
(
down6
);
tester
.
closeArena
(
down6
.
pointer
);
tester
.
route
(
down6
);
expect
(
recognized
,
<
String
>[
'tapSecondary'
]);
});
testGesture
(
'A primary double tap recognizer forms competion with a primary tap recognizer'
,
(
GestureTester
tester
)
{
doubleTap
.
addPointer
(
down1
);
tapPrimary
.
addPointer
(
down1
);
tester
.
closeArena
(
down1
.
pointer
);
tester
.
route
(
down1
);
expect
(
recognized
,
<
String
>[]);
tester
.
async
.
elapse
(
const
Duration
(
milliseconds:
300
));
expect
(
recognized
,
<
String
>[
'tapPrimary'
]);
});
});
testGesture
(
'A secondary double tap should not trigger primary'
,
(
GestureTester
tester
)
{
final
List
<
String
>
recognized
=
<
String
>[];
final
DoubleTapGestureRecognizer
doubleTap
=
DoubleTapGestureRecognizer
()
..
onDoubleTap
=
()
{
recognized
.
add
(
'primary'
);
};
// Down/up pair 7: normal tap sequence close to pair 6
const
PointerDownEvent
down7
=
PointerDownEvent
(
pointer:
7
,
position:
Offset
(
10.0
,
10.0
),
buttons:
kSecondaryMouseButton
,
);
const
PointerUpEvent
up7
=
PointerUpEvent
(
pointer:
7
,
position:
Offset
(
11.0
,
9.0
),
);
doubleTap
.
addPointer
(
down6
);
tester
.
closeArena
(
6
);
tester
.
route
(
down6
);
tester
.
route
(
up6
);
GestureBinding
.
instance
.
gestureArena
.
sweep
(
6
);
tester
.
async
.
elapse
(
const
Duration
(
milliseconds:
100
));
doubleTap
.
addPointer
(
down7
);
tester
.
closeArena
(
7
);
tester
.
route
(
down7
);
tester
.
route
(
up7
);
expect
(
recognized
,
<
String
>[]);
recognized
.
clear
();
doubleTap
.
dispose
();
});
}
}
packages/flutter/test/gestures/drag_test.dart
View file @
60a1b2b9
...
@@ -13,7 +13,7 @@ void main() {
...
@@ -13,7 +13,7 @@ void main() {
testGesture
(
'Should recognize pan'
,
(
GestureTester
tester
)
{
testGesture
(
'Should recognize pan'
,
(
GestureTester
tester
)
{
final
PanGestureRecognizer
pan
=
PanGestureRecognizer
();
final
PanGestureRecognizer
pan
=
PanGestureRecognizer
();
final
TapGestureRecognizer
tap
=
TapGestureRecognizer
()
..
onTap
=
()
{}
;
final
TapGestureRecognizer
tap
=
TapGestureRecognizer
();
bool
didStartPan
=
false
;
bool
didStartPan
=
false
;
pan
.
onStart
=
(
_
)
{
pan
.
onStart
=
(
_
)
{
...
@@ -81,8 +81,7 @@ void main() {
...
@@ -81,8 +81,7 @@ void main() {
testGesture
(
'Should report most recent point to onStart by default'
,
(
GestureTester
tester
)
{
testGesture
(
'Should report most recent point to onStart by default'
,
(
GestureTester
tester
)
{
final
HorizontalDragGestureRecognizer
drag
=
HorizontalDragGestureRecognizer
();
final
HorizontalDragGestureRecognizer
drag
=
HorizontalDragGestureRecognizer
();
final
VerticalDragGestureRecognizer
competingDrag
=
VerticalDragGestureRecognizer
()
final
VerticalDragGestureRecognizer
competingDrag
=
VerticalDragGestureRecognizer
();
..
onStart
=
(
_
)
{};
Offset
positionAtOnStart
;
Offset
positionAtOnStart
;
drag
.
onStart
=
(
DragStartDetails
details
)
{
drag
.
onStart
=
(
DragStartDetails
details
)
{
...
@@ -104,9 +103,9 @@ void main() {
...
@@ -104,9 +103,9 @@ void main() {
});
});
testGesture
(
'Should report most recent point to onStart with a start configuration'
,
(
GestureTester
tester
)
{
testGesture
(
'Should report most recent point to onStart with a start configuration'
,
(
GestureTester
tester
)
{
final
HorizontalDragGestureRecognizer
drag
=
HorizontalDragGestureRecognizer
();
final
HorizontalDragGestureRecognizer
drag
=
final
VerticalDragGestureRecognizer
competingDrag
=
VerticalDragGestureRecognizer
()
HorizontalDragGestureRecognizer
();
..
onStart
=
(
_
)
{}
;
final
VerticalDragGestureRecognizer
competingDrag
=
VerticalDragGestureRecognizer
()
;
Offset
positionAtOnStart
;
Offset
positionAtOnStart
;
drag
.
onStart
=
(
DragStartDetails
details
)
{
drag
.
onStart
=
(
DragStartDetails
details
)
{
...
@@ -219,11 +218,9 @@ void main() {
...
@@ -219,11 +218,9 @@ void main() {
// TODO(jslavitz): Revert these tests.
// TODO(jslavitz): Revert these tests.
testGesture
(
'Should report initial down point to onStart with a down configuration'
,
(
GestureTester
tester
)
{
testGesture
(
'Should report initial down point to onStart with a down configuration'
,
(
GestureTester
tester
)
{
final
HorizontalDragGestureRecognizer
drag
=
HorizontalDragGestureRecognizer
()
final
HorizontalDragGestureRecognizer
drag
=
..
dragStartBehavior
=
DragStartBehavior
.
down
;
HorizontalDragGestureRecognizer
()
..
dragStartBehavior
=
DragStartBehavior
.
down
;
final
VerticalDragGestureRecognizer
competingDrag
=
VerticalDragGestureRecognizer
()
final
VerticalDragGestureRecognizer
competingDrag
=
VerticalDragGestureRecognizer
()
..
dragStartBehavior
=
DragStartBehavior
.
down
;
..
dragStartBehavior
=
DragStartBehavior
.
down
..
onStart
=
(
_
)
{};
Offset
positionAtOnStart
;
Offset
positionAtOnStart
;
drag
.
onStart
=
(
DragStartDetails
details
)
{
drag
.
onStart
=
(
DragStartDetails
details
)
{
...
@@ -599,248 +596,4 @@ void main() {
...
@@ -599,248 +596,4 @@ void main() {
drag
.
dispose
();
drag
.
dispose
();
});
});
group
(
'Enforce consistent-button restriction:'
,
()
{
PanGestureRecognizer
pan
;
TapGestureRecognizer
tap
;
final
List
<
String
>
logs
=
<
String
>[];
setUp
(()
{
tap
=
TapGestureRecognizer
()
..
onTap
=
()
{};
// Need a callback to enable competition
pan
=
PanGestureRecognizer
()
..
onStart
=
(
DragStartDetails
details
)
{
logs
.
add
(
'start'
);
}
..
onDown
=
(
DragDownDetails
details
)
{
logs
.
add
(
'down'
);
}
..
onUpdate
=
(
DragUpdateDetails
details
)
{
logs
.
add
(
'update'
);
}
..
onCancel
=
()
{
logs
.
add
(
'cancel'
);
}
..
onEnd
=
(
DragEndDetails
details
)
{
logs
.
add
(
'end'
);
};
});
tearDown
(()
{
pan
.
dispose
();
tap
.
dispose
();
logs
.
clear
();
});
testGesture
(
'Button change before acceptance should lead to immediate cancel'
,
(
GestureTester
tester
)
{
final
TestPointer
pointer
=
TestPointer
(
5
,
PointerDeviceKind
.
mouse
,
kPrimaryButton
);
final
PointerDownEvent
down
=
pointer
.
down
(
const
Offset
(
10.0
,
10.0
));
pan
.
addPointer
(
down
);
tap
.
addPointer
(
down
);
tester
.
closeArena
(
5
);
tester
.
route
(
down
);
expect
(
logs
,
<
String
>[
'down'
]);
// Move out of slop so make sure button changes takes priority over slops
tester
.
route
(
pointer
.
move
(
const
Offset
(
30.0
,
30.0
),
buttons:
kSecondaryButton
));
expect
(
logs
,
<
String
>[
'down'
,
'cancel'
]);
tester
.
route
(
pointer
.
up
());
});
testGesture
(
'Button change before acceptance should not prevent the next drag'
,
(
GestureTester
tester
)
{
{
// First drag (which is canceled)
final
TestPointer
pointer
=
TestPointer
(
5
,
PointerDeviceKind
.
mouse
,
kPrimaryButton
);
final
PointerDownEvent
down
=
pointer
.
down
(
const
Offset
(
10.0
,
10.0
));
pan
.
addPointer
(
down
);
tap
.
addPointer
(
down
);
tester
.
closeArena
(
down
.
pointer
);
tester
.
route
(
down
);
tester
.
route
(
pointer
.
move
(
const
Offset
(
10.0
,
10.0
),
buttons:
kSecondaryButton
));
tester
.
route
(
pointer
.
up
());
expect
(
logs
,
<
String
>[
'down'
,
'cancel'
]);
}
logs
.
clear
();
final
TestPointer
pointer2
=
TestPointer
(
6
,
PointerDeviceKind
.
mouse
,
kPrimaryButton
);
final
PointerDownEvent
down2
=
pointer2
.
down
(
const
Offset
(
10.0
,
10.0
));
pan
.
addPointer
(
down2
);
tap
.
addPointer
(
down2
);
tester
.
closeArena
(
down2
.
pointer
);
tester
.
route
(
down2
);
expect
(
logs
,
<
String
>[
'down'
]);
tester
.
route
(
pointer2
.
move
(
const
Offset
(
30.0
,
30.0
)));
expect
(
logs
,
<
String
>[
'down'
,
'start'
]);
tester
.
route
(
pointer2
.
up
());
expect
(
logs
,
<
String
>[
'down'
,
'start'
,
'end'
]);
});
testGesture
(
'Button change after acceptance should lead to immediate end'
,
(
GestureTester
tester
)
{
final
TestPointer
pointer
=
TestPointer
(
5
,
PointerDeviceKind
.
mouse
,
kPrimaryButton
);
final
PointerDownEvent
down
=
pointer
.
down
(
const
Offset
(
10.0
,
10.0
));
pan
.
addPointer
(
down
);
tap
.
addPointer
(
down
);
tester
.
closeArena
(
down
.
pointer
);
tester
.
route
(
down
);
expect
(
logs
,
<
String
>[
'down'
]);
tester
.
route
(
pointer
.
move
(
const
Offset
(
30.0
,
30.0
)));
expect
(
logs
,
<
String
>[
'down'
,
'start'
]);
tester
.
route
(
pointer
.
move
(
const
Offset
(
30.0
,
30.0
),
buttons:
kSecondaryButton
));
expect
(
logs
,
<
String
>[
'down'
,
'start'
,
'end'
]);
// Make sure no further updates are sent
tester
.
route
(
pointer
.
move
(
const
Offset
(
50.0
,
50.0
)));
expect
(
logs
,
<
String
>[
'down'
,
'start'
,
'end'
]);
tester
.
route
(
pointer
.
up
());
});
testGesture
(
'Button change after acceptance should not prevent the next drag'
,
(
GestureTester
tester
)
{
{
// First drag (which is canceled)
final
TestPointer
pointer
=
TestPointer
(
5
,
PointerDeviceKind
.
mouse
,
kPrimaryButton
);
final
PointerDownEvent
down
=
pointer
.
down
(
const
Offset
(
10.0
,
10.0
));
pan
.
addPointer
(
down
);
tap
.
addPointer
(
down
);
tester
.
closeArena
(
down
.
pointer
);
tester
.
route
(
down
);
tester
.
route
(
pointer
.
move
(
const
Offset
(
30.0
,
30.0
)));
tester
.
route
(
pointer
.
move
(
const
Offset
(
30.0
,
31.0
),
buttons:
kSecondaryButton
));
tester
.
route
(
pointer
.
up
());
expect
(
logs
,
<
String
>[
'down'
,
'start'
,
'end'
]);
}
logs
.
clear
();
final
TestPointer
pointer2
=
TestPointer
(
6
,
PointerDeviceKind
.
mouse
,
kPrimaryButton
);
final
PointerDownEvent
down2
=
pointer2
.
down
(
const
Offset
(
10.0
,
10.0
));
pan
.
addPointer
(
down2
);
tap
.
addPointer
(
down2
);
tester
.
closeArena
(
down2
.
pointer
);
tester
.
route
(
down2
);
expect
(
logs
,
<
String
>[
'down'
]);
tester
.
route
(
pointer2
.
move
(
const
Offset
(
30.0
,
30.0
)));
expect
(
logs
,
<
String
>[
'down'
,
'start'
]);
tester
.
route
(
pointer2
.
up
());
expect
(
logs
,
<
String
>[
'down'
,
'start'
,
'end'
]);
});
});
group
(
'Recognizers listening on different buttons do not form competition:'
,
()
{
// This test is assisted by tap recognizers. If a tap gesture has
// no competing recognizers, a pointer down event triggers its onTapDown
// immediately; if there are competitors, onTapDown is triggered after a
// timeout.
// The following tests make sure that drag recognizers do not form
// competition with a tap gesture recognizer listening on a different button.
final
List
<
String
>
recognized
=
<
String
>[];
TapGestureRecognizer
tapPrimary
;
TapGestureRecognizer
tapSecondary
;
PanGestureRecognizer
pan
;
setUp
(()
{
tapPrimary
=
TapGestureRecognizer
()
..
onTapDown
=
(
TapDownDetails
details
)
{
recognized
.
add
(
'tapPrimary'
);
};
tapSecondary
=
TapGestureRecognizer
()
..
onSecondaryTapDown
=
(
TapDownDetails
details
)
{
recognized
.
add
(
'tapSecondary'
);
};
pan
=
PanGestureRecognizer
()
..
onStart
=
(
_
)
{
recognized
.
add
(
'drag'
);
};
});
tearDown
(()
{
recognized
.
clear
();
tapPrimary
.
dispose
();
tapSecondary
.
dispose
();
pan
.
dispose
();
});
testGesture
(
'A primary pan recognizer does not form competion with a secondary tap recognizer'
,
(
GestureTester
tester
)
{
final
TestPointer
pointer
=
TestPointer
(
1
,
PointerDeviceKind
.
touch
,
kSecondaryButton
,
);
final
PointerDownEvent
down
=
pointer
.
down
(
const
Offset
(
10
,
10
));
pan
.
addPointer
(
down
);
tapSecondary
.
addPointer
(
down
);
tester
.
closeArena
(
down
.
pointer
);
tester
.
route
(
down
);
expect
(
recognized
,
<
String
>[
'tapSecondary'
]);
});
testGesture
(
'A primary pan recognizer forms competion with a primary tap recognizer'
,
(
GestureTester
tester
)
{
final
TestPointer
pointer
=
TestPointer
(
1
,
PointerDeviceKind
.
touch
,
kPrimaryButton
,
);
final
PointerDownEvent
down
=
pointer
.
down
(
const
Offset
(
10
,
10
));
pan
.
addPointer
(
down
);
tapPrimary
.
addPointer
(
down
);
tester
.
closeArena
(
down
.
pointer
);
tester
.
route
(
down
);
expect
(
recognized
,
<
String
>[]);
tester
.
route
(
pointer
.
up
());
expect
(
recognized
,
<
String
>[
'tapPrimary'
]);
});
});
testGesture
(
'A secondary drag should not trigger primary'
,
(
GestureTester
tester
)
{
final
List
<
String
>
recognized
=
<
String
>[];
final
TapGestureRecognizer
tap
=
TapGestureRecognizer
()
..
onTap
=
()
{};
// Need a listener to enable competetion.
final
PanGestureRecognizer
pan
=
PanGestureRecognizer
()
..
onDown
=
(
DragDownDetails
details
)
{
recognized
.
add
(
'primaryDown'
);
}
..
onStart
=
(
DragStartDetails
details
)
{
recognized
.
add
(
'primaryStart'
);
}
..
onUpdate
=
(
DragUpdateDetails
details
)
{
recognized
.
add
(
'primaryUpdate'
);
}
..
onEnd
=
(
DragEndDetails
details
)
{
recognized
.
add
(
'primaryEnd'
);
}
..
onCancel
=
()
{
recognized
.
add
(
'primaryCancel'
);
};
final
TestPointer
pointer
=
TestPointer
(
5
,
PointerDeviceKind
.
touch
,
kSecondaryButton
,
);
final
PointerDownEvent
down
=
pointer
.
down
(
const
Offset
(
10.0
,
10.0
));
pan
.
addPointer
(
down
);
tap
.
addPointer
(
down
);
tester
.
closeArena
(
5
);
tester
.
route
(
down
);
tester
.
route
(
pointer
.
move
(
const
Offset
(
20.0
,
30.0
)));
tester
.
route
(
pointer
.
move
(
const
Offset
(
20.0
,
25.0
)));
tester
.
route
(
pointer
.
up
());
expect
(
recognized
,
<
String
>[]);
recognized
.
clear
();
pan
.
dispose
();
tap
.
dispose
();
recognized
.
clear
();
});
}
}
packages/flutter/test/gestures/events_test.dart
View file @
60a1b2b9
...
@@ -20,20 +20,6 @@ void main() {
...
@@ -20,20 +20,6 @@ void main() {
expect
(
nthStylusButton
(
2
),
kSecondaryStylusButton
);
expect
(
nthStylusButton
(
2
),
kSecondaryStylusButton
);
});
});
testGesture
(
'smallestButton tests'
,
(
GestureTester
tester
)
{
expect
(
smallestButton
(
0x0
),
equals
(
0x0
));
expect
(
smallestButton
(
0x1
),
equals
(
0x1
));
expect
(
smallestButton
(
0x200
),
equals
(
0x200
));
expect
(
smallestButton
(
0x220
),
equals
(
0x20
));
});
testGesture
(
'isSingleButton tests'
,
(
GestureTester
tester
)
{
expect
(
isSingleButton
(
0x0
),
isFalse
);
expect
(
isSingleButton
(
0x1
),
isTrue
);
expect
(
isSingleButton
(
0x200
),
isTrue
);
expect
(
isSingleButton
(
0x220
),
isFalse
);
});
group
(
'Default values of PointerEvents:'
,
()
{
group
(
'Default values of PointerEvents:'
,
()
{
// Some parameters are intentionally set to a non-trivial value.
// Some parameters are intentionally set to a non-trivial value.
...
...
packages/flutter/test/gestures/gesture_binding_test.dart
View file @
60a1b2b9
...
@@ -318,38 +318,7 @@ void main() {
...
@@ -318,38 +318,7 @@ void main() {
}
}
});
});
test
(
'Should synthesise kPrimaryButton for unknown devices'
,
()
{
test
(
'Should not synthesise kPrimaryButton for certain devices'
,
()
{
final
Offset
location
=
const
Offset
(
10.0
,
10.0
)
*
ui
.
window
.
devicePixelRatio
;
const
PointerDeviceKind
kind
=
PointerDeviceKind
.
unknown
;
final
ui
.
PointerDataPacket
packet
=
ui
.
PointerDataPacket
(
data:
<
ui
.
PointerData
>[
ui
.
PointerData
(
change:
ui
.
PointerChange
.
add
,
kind:
kind
,
physicalX:
location
.
dx
,
physicalY:
location
.
dy
),
ui
.
PointerData
(
change:
ui
.
PointerChange
.
hover
,
kind:
kind
,
physicalX:
location
.
dx
,
physicalY:
location
.
dy
),
ui
.
PointerData
(
change:
ui
.
PointerChange
.
down
,
kind:
kind
,
physicalX:
location
.
dx
,
physicalY:
location
.
dy
),
ui
.
PointerData
(
change:
ui
.
PointerChange
.
move
,
kind:
kind
,
physicalX:
location
.
dx
,
physicalY:
location
.
dy
),
ui
.
PointerData
(
change:
ui
.
PointerChange
.
up
,
kind:
kind
,
physicalX:
location
.
dx
,
physicalY:
location
.
dy
),
]
);
final
List
<
PointerEvent
>
events
=
PointerEventConverter
.
expand
(
packet
.
data
,
ui
.
window
.
devicePixelRatio
).
toList
();
expect
(
events
.
length
,
5
);
expect
(
events
[
0
].
runtimeType
,
equals
(
PointerAddedEvent
));
expect
(
events
[
0
].
buttons
,
equals
(
0
));
expect
(
events
[
1
].
runtimeType
,
equals
(
PointerHoverEvent
));
expect
(
events
[
1
].
buttons
,
equals
(
0
));
expect
(
events
[
2
].
runtimeType
,
equals
(
PointerDownEvent
));
expect
(
events
[
2
].
buttons
,
equals
(
kPrimaryButton
));
expect
(
events
[
3
].
runtimeType
,
equals
(
PointerMoveEvent
));
expect
(
events
[
3
].
buttons
,
equals
(
kPrimaryButton
));
expect
(
events
[
4
].
runtimeType
,
equals
(
PointerUpEvent
));
expect
(
events
[
4
].
buttons
,
equals
(
0
));
PointerEventConverter
.
clearPointers
();
});
test
(
'Should not synthesise kPrimaryButton for mouse'
,
()
{
final
Offset
location
=
const
Offset
(
10.0
,
10.0
)
*
ui
.
window
.
devicePixelRatio
;
final
Offset
location
=
const
Offset
(
10.0
,
10.0
)
*
ui
.
window
.
devicePixelRatio
;
for
(
PointerDeviceKind
kind
in
<
PointerDeviceKind
>[
for
(
PointerDeviceKind
kind
in
<
PointerDeviceKind
>[
PointerDeviceKind
.
mouse
,
PointerDeviceKind
.
mouse
,
...
...
packages/flutter/test/gestures/long_press_test.dart
View file @
60a1b2b9
...
@@ -7,7 +7,6 @@ import 'package:flutter/gestures.dart';
...
@@ -7,7 +7,6 @@ import 'package:flutter/gestures.dart';
import
'../flutter_test_alternative.dart'
;
import
'../flutter_test_alternative.dart'
;
import
'gesture_tester.dart'
;
import
'gesture_tester.dart'
;
// Down/move/up pair 1: normal tap sequence
const
PointerDownEvent
down
=
PointerDownEvent
(
const
PointerDownEvent
down
=
PointerDownEvent
(
pointer:
5
,
pointer:
5
,
position:
Offset
(
10
,
10
),
position:
Offset
(
10
,
10
),
...
@@ -23,29 +22,6 @@ const PointerMoveEvent move = PointerMoveEvent(
...
@@ -23,29 +22,6 @@ const PointerMoveEvent move = PointerMoveEvent(
position:
Offset
(
100
,
200
),
position:
Offset
(
100
,
200
),
);
);
// Down/up pair 2: normal tap sequence far away from pair 1
const
PointerDownEvent
down2
=
PointerDownEvent
(
pointer:
6
,
position:
Offset
(
10
,
10
),
);
const
PointerUpEvent
up2
=
PointerUpEvent
(
pointer:
6
,
position:
Offset
(
11
,
9
),
);
// Down/up pair 3: tap sequence with secondary button
const
PointerDownEvent
down3
=
PointerDownEvent
(
pointer:
7
,
position:
Offset
(
30
,
30
),
buttons:
kSecondaryButton
,
);
const
PointerUpEvent
up3
=
PointerUpEvent
(
pointer:
7
,
position:
Offset
(
31
,
29
),
);
void
main
(
)
{
void
main
(
)
{
setUp
(
ensureGestureBinding
);
setUp
(
ensureGestureBinding
);
...
@@ -211,48 +187,6 @@ void main() {
...
@@ -211,48 +187,6 @@ void main() {
longPress
.
dispose
();
longPress
.
dispose
();
});
});
testGesture
(
'Should not recognize long press with more than one buttons'
,
(
GestureTester
tester
)
{
longPress
.
addPointer
(
const
PointerDownEvent
(
pointer:
5
,
kind:
PointerDeviceKind
.
mouse
,
buttons:
kSecondaryMouseButton
|
kMiddleMouseButton
,
position:
Offset
(
10
,
10
),
));
tester
.
closeArena
(
5
);
expect
(
longPressDown
,
isFalse
);
tester
.
route
(
down
);
expect
(
longPressDown
,
isFalse
);
tester
.
async
.
elapse
(
const
Duration
(
milliseconds:
1000
));
expect
(
longPressDown
,
isFalse
);
tester
.
route
(
up
);
expect
(
longPressUp
,
isFalse
);
longPress
.
dispose
();
});
testGesture
(
'Should cancel long press when buttons change before acceptance'
,
(
GestureTester
tester
)
{
longPress
.
addPointer
(
down
);
tester
.
closeArena
(
5
);
expect
(
longPressDown
,
isFalse
);
tester
.
route
(
down
);
expect
(
longPressDown
,
isFalse
);
tester
.
async
.
elapse
(
const
Duration
(
milliseconds:
300
));
expect
(
longPressDown
,
isFalse
);
tester
.
route
(
const
PointerMoveEvent
(
pointer:
5
,
kind:
PointerDeviceKind
.
mouse
,
buttons:
kMiddleMouseButton
,
position:
Offset
(
10
,
10
),
));
expect
(
longPressDown
,
isFalse
);
tester
.
async
.
elapse
(
const
Duration
(
milliseconds:
700
));
expect
(
longPressDown
,
isFalse
);
tester
.
route
(
up
);
expect
(
longPressUp
,
isFalse
);
longPress
.
dispose
();
});
});
});
group
(
'long press drag'
,
()
{
group
(
'long press drag'
,
()
{
...
@@ -345,107 +279,6 @@ void main() {
...
@@ -345,107 +279,6 @@ void main() {
});
});
});
});
group
(
'Enforce consistent-button restriction:'
,
()
{
// In sequence between `down` and `up` but with buttons changed
const
PointerMoveEvent
moveR
=
PointerMoveEvent
(
pointer:
5
,
buttons:
kSecondaryButton
,
position:
Offset
(
10
,
10
),
);
final
List
<
String
>
recognized
=
<
String
>[];
LongPressGestureRecognizer
longPress
;
setUp
(()
{
longPress
=
LongPressGestureRecognizer
()
..
onLongPressStart
=
(
LongPressStartDetails
details
)
{
recognized
.
add
(
'start'
);
}
..
onLongPressEnd
=
(
LongPressEndDetails
details
)
{
recognized
.
add
(
'end'
);
};
});
tearDown
(()
{
longPress
.
dispose
();
recognized
.
clear
();
});
testGesture
(
'Should cancel long press when buttons change before acceptance'
,
(
GestureTester
tester
)
{
// First press
longPress
.
addPointer
(
down
);
tester
.
closeArena
(
down
.
pointer
);
tester
.
route
(
down
);
tester
.
async
.
elapse
(
const
Duration
(
milliseconds:
300
));
tester
.
route
(
moveR
);
expect
(
recognized
,
<
String
>[]);
tester
.
async
.
elapse
(
const
Duration
(
milliseconds:
700
));
tester
.
route
(
up
);
expect
(
recognized
,
<
String
>[]);
});
testGesture
(
'Buttons change before acceptance should not prevent the next long press'
,
(
GestureTester
tester
)
{
// First press
longPress
.
addPointer
(
down
);
tester
.
closeArena
(
down
.
pointer
);
tester
.
route
(
down
);
tester
.
async
.
elapse
(
const
Duration
(
milliseconds:
300
));
tester
.
route
(
moveR
);
tester
.
async
.
elapse
(
const
Duration
(
milliseconds:
700
));
tester
.
route
(
up
);
recognized
.
clear
();
// Second press
longPress
.
addPointer
(
down2
);
tester
.
closeArena
(
down2
.
pointer
);
tester
.
route
(
down2
);
tester
.
async
.
elapse
(
const
Duration
(
milliseconds:
1000
));
expect
(
recognized
,
<
String
>[
'start'
]);
recognized
.
clear
();
tester
.
route
(
up2
);
expect
(
recognized
,
<
String
>[
'end'
]);
});
testGesture
(
'Should cancel long press when buttons change after acceptance'
,
(
GestureTester
tester
)
{
// First press
longPress
.
addPointer
(
down
);
tester
.
closeArena
(
down
.
pointer
);
tester
.
route
(
down
);
tester
.
async
.
elapse
(
const
Duration
(
milliseconds:
1000
));
expect
(
recognized
,
<
String
>[
'start'
]);
recognized
.
clear
();
tester
.
route
(
moveR
);
expect
(
recognized
,
<
String
>[]);
tester
.
route
(
up
);
expect
(
recognized
,
<
String
>[]);
});
testGesture
(
'Buttons change after acceptance should not prevent the next long press'
,
(
GestureTester
tester
)
{
// First press
longPress
.
addPointer
(
down
);
tester
.
closeArena
(
down
.
pointer
);
tester
.
route
(
down
);
tester
.
async
.
elapse
(
const
Duration
(
milliseconds:
1000
));
tester
.
route
(
moveR
);
tester
.
route
(
up
);
recognized
.
clear
();
// Second press
longPress
.
addPointer
(
down2
);
tester
.
closeArena
(
down2
.
pointer
);
tester
.
route
(
down2
);
tester
.
async
.
elapse
(
const
Duration
(
milliseconds:
1000
));
expect
(
recognized
,
<
String
>[
'start'
]);
recognized
.
clear
();
tester
.
route
(
up2
);
expect
(
recognized
,
<
String
>[
'end'
]);
});
});
testGesture
(
'Can filter long press based on device kind'
,
(
GestureTester
tester
)
{
testGesture
(
'Can filter long press based on device kind'
,
(
GestureTester
tester
)
{
final
LongPressGestureRecognizer
mouseLongPress
=
LongPressGestureRecognizer
(
kind:
PointerDeviceKind
.
mouse
);
final
LongPressGestureRecognizer
mouseLongPress
=
LongPressGestureRecognizer
(
kind:
PointerDeviceKind
.
mouse
);
...
@@ -485,107 +318,4 @@ void main() {
...
@@ -485,107 +318,4 @@ void main() {
mouseLongPress
.
dispose
();
mouseLongPress
.
dispose
();
});
});
group
(
'Recognizers listening on different buttons do not form competition:'
,
()
{
// This test is assisted by tap recognizers. If a tap gesture has
// no competing recognizers, a pointer down event triggers its onTapDown
// immediately; if there are competitors, onTapDown is triggered after a
// timeout.
// The following tests make sure that long press recognizers do not form
// competition with a tap gesture recognizer listening on a different button.
final
List
<
String
>
recognized
=
<
String
>[];
TapGestureRecognizer
tapPrimary
;
TapGestureRecognizer
tapSecondary
;
LongPressGestureRecognizer
longPress
;
setUp
(()
{
tapPrimary
=
TapGestureRecognizer
()
..
onTapDown
=
(
TapDownDetails
details
)
{
recognized
.
add
(
'tapPrimary'
);
};
tapSecondary
=
TapGestureRecognizer
()
..
onSecondaryTapDown
=
(
TapDownDetails
details
)
{
recognized
.
add
(
'tapSecondary'
);
};
longPress
=
LongPressGestureRecognizer
()
..
onLongPressStart
=
(
_
)
{
recognized
.
add
(
'longPress'
);
};
});
tearDown
(()
{
recognized
.
clear
();
tapPrimary
.
dispose
();
tapSecondary
.
dispose
();
longPress
.
dispose
();
});
testGesture
(
'A primary long press recognizer does not form competion with a secondary tap recognizer'
,
(
GestureTester
tester
)
{
longPress
.
addPointer
(
down3
);
tapSecondary
.
addPointer
(
down3
);
tester
.
closeArena
(
down3
.
pointer
);
tester
.
route
(
down3
);
expect
(
recognized
,
<
String
>[
'tapSecondary'
]);
});
testGesture
(
'A primary long press recognizer forms competion with a primary tap recognizer'
,
(
GestureTester
tester
)
{
longPress
.
addPointer
(
down
);
tapPrimary
.
addPointer
(
down
);
tester
.
closeArena
(
down
.
pointer
);
tester
.
route
(
down
);
expect
(
recognized
,
<
String
>[]);
tester
.
route
(
up
);
expect
(
recognized
,
<
String
>[
'tapPrimary'
]);
});
});
testGesture
(
'A secondary long press should not trigger primary'
,
(
GestureTester
tester
)
{
final
List
<
String
>
recognized
=
<
String
>[];
final
LongPressGestureRecognizer
longPress
=
LongPressGestureRecognizer
()
..
onLongPressStart
=
(
LongPressStartDetails
details
)
{
recognized
.
add
(
'primaryStart'
);
}
..
onLongPress
=
()
{
recognized
.
add
(
'primary'
);
}
..
onLongPressMoveUpdate
=
(
LongPressMoveUpdateDetails
details
)
{
recognized
.
add
(
'primaryUpdate'
);
}
..
onLongPressEnd
=
(
LongPressEndDetails
details
)
{
recognized
.
add
(
'primaryEnd'
);
}
..
onLongPressUp
=
()
{
recognized
.
add
(
'primaryUp'
);
};
const
PointerDownEvent
down2
=
PointerDownEvent
(
pointer:
2
,
buttons:
kSecondaryButton
,
position:
Offset
(
30.0
,
30.0
),
);
const
PointerMoveEvent
move2
=
PointerMoveEvent
(
pointer:
2
,
buttons:
kSecondaryButton
,
position:
Offset
(
100
,
200
),
);
const
PointerUpEvent
up2
=
PointerUpEvent
(
pointer:
2
,
position:
Offset
(
100
,
201
),
);
longPress
.
addPointer
(
down2
);
tester
.
closeArena
(
2
);
tester
.
route
(
down2
);
tester
.
async
.
elapse
(
const
Duration
(
milliseconds:
700
));
tester
.
route
(
move2
);
tester
.
route
(
up2
);
expect
(
recognized
,
<
String
>[]);
longPress
.
dispose
();
recognized
.
clear
();
});
}
}
packages/flutter/test/gestures/tap_test.dart
View file @
60a1b2b9
...
@@ -73,18 +73,6 @@ void main() {
...
@@ -73,18 +73,6 @@ void main() {
position:
Offset
(
22.0
,
22.0
),
position:
Offset
(
22.0
,
22.0
),
);
);
// Down/up sequence 5: tap sequence with secondary button
const
PointerDownEvent
down5
=
PointerDownEvent
(
pointer:
5
,
position:
Offset
(
20.0
,
20.0
),
buttons:
kSecondaryButton
,
);
const
PointerUpEvent
up5
=
PointerUpEvent
(
pointer:
5
,
position:
Offset
(
20.0
,
20.0
),
);
testGesture
(
'Should recognize tap'
,
(
GestureTester
tester
)
{
testGesture
(
'Should recognize tap'
,
(
GestureTester
tester
)
{
final
TapGestureRecognizer
tap
=
TapGestureRecognizer
();
final
TapGestureRecognizer
tap
=
TapGestureRecognizer
();
...
@@ -451,48 +439,6 @@ void main() {
...
@@ -451,48 +439,6 @@ void main() {
tap
.
dispose
();
tap
.
dispose
();
});
});
testGesture
(
'PointerCancelEvent after exceeding deadline cancels tap'
,
(
GestureTester
tester
)
{
const
PointerDownEvent
down
=
PointerDownEvent
(
pointer:
5
,
position:
Offset
(
10.0
,
10.0
),
);
const
PointerCancelEvent
cancel
=
PointerCancelEvent
(
pointer:
5
,
position:
Offset
(
10.0
,
10.0
),
);
final
TapGestureRecognizer
tap
=
TapGestureRecognizer
();
final
HorizontalDragGestureRecognizer
drag
=
HorizontalDragGestureRecognizer
()
..
onStart
=
(
_
)
{};
// Need a callback to compete
final
List
<
String
>
recognized
=
<
String
>[];
tap
.
onTapDown
=
(
_
)
{
recognized
.
add
(
'down'
);
};
tap
.
onTapUp
=
(
_
)
{
recognized
.
add
(
'up'
);
};
tap
.
onTap
=
()
{
recognized
.
add
(
'tap'
);
};
tap
.
onTapCancel
=
()
{
recognized
.
add
(
'cancel'
);
};
tap
.
addPointer
(
down
);
drag
.
addPointer
(
down
);
tester
.
closeArena
(
5
);
tester
.
route
(
down
);
expect
(
recognized
,
<
String
>[]);
tester
.
async
.
elapse
(
const
Duration
(
milliseconds:
1000
));
expect
(
recognized
,
<
String
>[
'down'
]);
tester
.
route
(
cancel
);
expect
(
recognized
,
<
String
>[
'down'
,
'cancel'
]);
tap
.
dispose
();
drag
.
dispose
();
});
testGesture
(
'losing tap gesture recognizer does not send onTapCancel'
,
(
GestureTester
tester
)
{
testGesture
(
'losing tap gesture recognizer does not send onTapCancel'
,
(
GestureTester
tester
)
{
final
TapGestureRecognizer
tap
=
TapGestureRecognizer
();
final
TapGestureRecognizer
tap
=
TapGestureRecognizer
();
final
HorizontalDragGestureRecognizer
drag
=
HorizontalDragGestureRecognizer
();
final
HorizontalDragGestureRecognizer
drag
=
HorizontalDragGestureRecognizer
();
...
@@ -521,282 +467,4 @@ void main() {
...
@@ -521,282 +467,4 @@ void main() {
tap
.
dispose
();
tap
.
dispose
();
drag
.
dispose
();
drag
.
dispose
();
});
});
group
(
'Enforce consistent-button restriction:'
,
()
{
// Change buttons during down-up sequence 1
const
PointerMoveEvent
move1lr
=
PointerMoveEvent
(
pointer:
1
,
position:
Offset
(
10.0
,
10.0
),
buttons:
kPrimaryMouseButton
|
kSecondaryMouseButton
,
);
const
PointerMoveEvent
move1r
=
PointerMoveEvent
(
pointer:
1
,
position:
Offset
(
10.0
,
10.0
),
buttons:
kSecondaryMouseButton
,
);
final
List
<
String
>
recognized
=
<
String
>[];
TapGestureRecognizer
tap
;
setUp
(()
{
tap
=
TapGestureRecognizer
()
..
onTapDown
=
(
TapDownDetails
details
)
{
recognized
.
add
(
'down'
);
}
..
onTapUp
=
(
TapUpDetails
details
)
{
recognized
.
add
(
'up'
);
}
..
onTapCancel
=
()
{
recognized
.
add
(
'cancel'
);
};
});
tearDown
(()
{
tap
.
dispose
();
recognized
.
clear
();
});
testGesture
(
'changing buttons before TapDown should cancel gesture without sending cancel'
,
(
GestureTester
tester
)
{
tap
.
addPointer
(
down1
);
tester
.
closeArena
(
1
);
expect
(
recognized
,
<
String
>[]);
tester
.
route
(
move1lr
);
expect
(
recognized
,
<
String
>[]);
tester
.
route
(
move1r
);
expect
(
recognized
,
<
String
>[]);
tester
.
route
(
up1
);
expect
(
recognized
,
<
String
>[]);
tap
.
dispose
();
});
testGesture
(
'changing buttons before TapDown should not prevent the next tap'
,
(
GestureTester
tester
)
{
tap
.
addPointer
(
down1
);
tester
.
closeArena
(
1
);
tester
.
route
(
move1lr
);
tester
.
route
(
move1r
);
tester
.
route
(
up1
);
expect
(
recognized
,
<
String
>[]);
tap
.
addPointer
(
down2
);
tester
.
closeArena
(
2
);
tester
.
async
.
elapse
(
const
Duration
(
milliseconds:
1000
));
tester
.
route
(
up2
);
expect
(
recognized
,
<
String
>[
'down'
,
'up'
]);
tap
.
dispose
();
});
testGesture
(
'changing buttons after TapDown should cancel gesture and send cancel'
,
(
GestureTester
tester
)
{
tap
.
addPointer
(
down1
);
tester
.
closeArena
(
1
);
expect
(
recognized
,
<
String
>[]);
tester
.
async
.
elapse
(
const
Duration
(
milliseconds:
1000
));
expect
(
recognized
,
<
String
>[
'down'
]);
tester
.
route
(
move1lr
);
expect
(
recognized
,
<
String
>[
'down'
,
'cancel'
]);
tester
.
route
(
move1r
);
expect
(
recognized
,
<
String
>[
'down'
,
'cancel'
]);
tester
.
route
(
up1
);
expect
(
recognized
,
<
String
>[
'down'
,
'cancel'
]);
tap
.
dispose
();
});
testGesture
(
'changing buttons after TapDown should not prevent the next tap'
,
(
GestureTester
tester
)
{
tap
.
addPointer
(
down1
);
tester
.
closeArena
(
1
);
tester
.
async
.
elapse
(
const
Duration
(
milliseconds:
1000
));
tester
.
route
(
move1lr
);
tester
.
route
(
move1r
);
tester
.
route
(
up1
);
GestureBinding
.
instance
.
gestureArena
.
sweep
(
1
);
expect
(
recognized
,
<
String
>[
'down'
,
'cancel'
]);
tap
.
addPointer
(
down2
);
tester
.
closeArena
(
2
);
tester
.
async
.
elapse
(
const
Duration
(
milliseconds:
1000
));
tester
.
route
(
up2
);
GestureBinding
.
instance
.
gestureArena
.
sweep
(
2
);
expect
(
recognized
,
<
String
>[
'down'
,
'cancel'
,
'down'
,
'up'
]);
tap
.
dispose
();
});
});
group
(
'Recognizers listening on different buttons do not form competition:'
,
()
{
// If a tap gesture has no competitors, a pointer down event triggers
// onTapDown immediately; if there are competitors, onTapDown is triggered
// after a timeout. The following tests make sure that tap recognizers
// listening on different buttons do not form competition.
final
List
<
String
>
recognized
=
<
String
>[];
TapGestureRecognizer
primary
;
TapGestureRecognizer
primary2
;
TapGestureRecognizer
secondary
;
setUp
(()
{
primary
=
TapGestureRecognizer
()
..
onTapDown
=
(
TapDownDetails
details
)
{
recognized
.
add
(
'primaryDown'
);
}
..
onTapUp
=
(
TapUpDetails
details
)
{
recognized
.
add
(
'primaryUp'
);
}
..
onTapCancel
=
()
{
recognized
.
add
(
'primaryCancel'
);
};
primary2
=
TapGestureRecognizer
()
..
onTapDown
=
(
TapDownDetails
details
)
{
recognized
.
add
(
'primary2Down'
);
}
..
onTapUp
=
(
TapUpDetails
details
)
{
recognized
.
add
(
'primary2Up'
);
}
..
onTapCancel
=
()
{
recognized
.
add
(
'primary2Cancel'
);
};
secondary
=
TapGestureRecognizer
()
..
onSecondaryTapDown
=
(
TapDownDetails
details
)
{
recognized
.
add
(
'secondaryDown'
);
}
..
onSecondaryTapUp
=
(
TapUpDetails
details
)
{
recognized
.
add
(
'secondaryUp'
);
}
..
onSecondaryTapCancel
=
()
{
recognized
.
add
(
'secondaryCancel'
);
};
});
tearDown
(()
{
recognized
.
clear
();
primary
.
dispose
();
primary2
.
dispose
();
secondary
.
dispose
();
});
testGesture
(
'A primary tap recognizer does not form competion with a secondary tap recognizer'
,
(
GestureTester
tester
)
{
primary
.
addPointer
(
down1
);
secondary
.
addPointer
(
down1
);
tester
.
closeArena
(
1
);
tester
.
route
(
down1
);
expect
(
recognized
,
<
String
>[
'primaryDown'
]);
recognized
.
clear
();
tester
.
route
(
up1
);
expect
(
recognized
,
<
String
>[
'primaryUp'
]);
});
testGesture
(
'A primary tap recognizer forms competion with another primary tap recognizer'
,
(
GestureTester
tester
)
{
primary
.
addPointer
(
down1
);
primary2
.
addPointer
(
down1
);
tester
.
closeArena
(
1
);
tester
.
route
(
down1
);
expect
(
recognized
,
<
String
>[]);
tester
.
async
.
elapse
(
const
Duration
(
milliseconds:
500
));
expect
(
recognized
,
<
String
>[
'primaryDown'
,
'primary2Down'
]);
});
});
group
(
'Gestures of different buttons trigger correct callbacks:'
,
()
{
final
List
<
String
>
recognized
=
<
String
>[];
TapGestureRecognizer
tap
;
const
PointerCancelEvent
cancel1
=
PointerCancelEvent
(
pointer:
1
,
);
const
PointerCancelEvent
cancel5
=
PointerCancelEvent
(
pointer:
5
,
);
setUp
(()
{
tap
=
TapGestureRecognizer
()
..
onTapDown
=
(
TapDownDetails
details
)
{
recognized
.
add
(
'primaryDown'
);
}
..
onTap
=
()
{
recognized
.
add
(
'primary'
);
}
..
onTapUp
=
(
TapUpDetails
details
)
{
recognized
.
add
(
'primaryUp'
);
}
..
onTapCancel
=
()
{
recognized
.
add
(
'primaryCancel'
);
}
..
onSecondaryTapDown
=
(
TapDownDetails
details
)
{
recognized
.
add
(
'secondaryDown'
);
}
..
onSecondaryTapUp
=
(
TapUpDetails
details
)
{
recognized
.
add
(
'secondaryUp'
);
}
..
onSecondaryTapCancel
=
()
{
recognized
.
add
(
'secondaryCancel'
);
};
});
tearDown
(()
{
recognized
.
clear
();
tap
.
dispose
();
});
testGesture
(
'A primary tap should trigger primary callbacks'
,
(
GestureTester
tester
)
{
tap
.
addPointer
(
down1
);
tester
.
closeArena
(
down1
.
pointer
);
expect
(
recognized
,
<
String
>[]);
tester
.
async
.
elapse
(
const
Duration
(
milliseconds:
500
));
expect
(
recognized
,
<
String
>[
'primaryDown'
]);
recognized
.
clear
();
tester
.
route
(
up1
);
expect
(
recognized
,
<
String
>[
'primaryUp'
,
'primary'
]);
GestureBinding
.
instance
.
gestureArena
.
sweep
(
down1
.
pointer
);
});
testGesture
(
'A primary tap cancel trigger primary callbacks'
,
(
GestureTester
tester
)
{
tap
.
addPointer
(
down1
);
tester
.
closeArena
(
down1
.
pointer
);
expect
(
recognized
,
<
String
>[]);
tester
.
async
.
elapse
(
const
Duration
(
milliseconds:
500
));
expect
(
recognized
,
<
String
>[
'primaryDown'
]);
recognized
.
clear
();
tester
.
route
(
cancel1
);
expect
(
recognized
,
<
String
>[
'primaryCancel'
]);
GestureBinding
.
instance
.
gestureArena
.
sweep
(
down1
.
pointer
);
});
testGesture
(
'A secondary tap should trigger secondary callbacks'
,
(
GestureTester
tester
)
{
tap
.
addPointer
(
down5
);
tester
.
closeArena
(
down5
.
pointer
);
expect
(
recognized
,
<
String
>[]);
tester
.
async
.
elapse
(
const
Duration
(
milliseconds:
500
));
expect
(
recognized
,
<
String
>[
'secondaryDown'
]);
recognized
.
clear
();
tester
.
route
(
up5
);
GestureBinding
.
instance
.
gestureArena
.
sweep
(
down5
.
pointer
);
expect
(
recognized
,
<
String
>[
'secondaryUp'
]);
});
testGesture
(
'A secondary tap cancel should trigger secondary callbacks'
,
(
GestureTester
tester
)
{
tap
.
addPointer
(
down5
);
tester
.
closeArena
(
down5
.
pointer
);
expect
(
recognized
,
<
String
>[]);
tester
.
async
.
elapse
(
const
Duration
(
milliseconds:
500
));
expect
(
recognized
,
<
String
>[
'secondaryDown'
]);
recognized
.
clear
();
tester
.
route
(
cancel5
);
GestureBinding
.
instance
.
gestureArena
.
sweep
(
down5
.
pointer
);
expect
(
recognized
,
<
String
>[
'secondaryCancel'
]);
});
});
}
}
packages/flutter/test/widgets/platform_view_test.dart
View file @
60a1b2b9
...
@@ -592,10 +592,7 @@ void main() {
...
@@ -592,10 +592,7 @@ void main() {
viewType:
'webview'
,
viewType:
'webview'
,
gestureRecognizers:
<
Factory
<
OneSequenceGestureRecognizer
>>{
gestureRecognizers:
<
Factory
<
OneSequenceGestureRecognizer
>>{
Factory
<
VerticalDragGestureRecognizer
>(
Factory
<
VerticalDragGestureRecognizer
>(
()
{
()
=>
VerticalDragGestureRecognizer
(),
return
VerticalDragGestureRecognizer
()
..
onStart
=
(
_
)
{};
// Add callback to enable recognizer
},
),
),
},
},
layoutDirection:
TextDirection
.
ltr
,
layoutDirection:
TextDirection
.
ltr
,
...
@@ -1266,10 +1263,7 @@ void main() {
...
@@ -1266,10 +1263,7 @@ void main() {
viewType:
'webview'
,
viewType:
'webview'
,
gestureRecognizers:
<
Factory
<
OneSequenceGestureRecognizer
>>{
gestureRecognizers:
<
Factory
<
OneSequenceGestureRecognizer
>>{
Factory
<
VerticalDragGestureRecognizer
>(
Factory
<
VerticalDragGestureRecognizer
>(
()
{
()
=>
VerticalDragGestureRecognizer
(),
return
VerticalDragGestureRecognizer
()
..
onStart
=
(
_
)
{};
// Add callback to enable recognizer
},
),
),
},
},
layoutDirection:
TextDirection
.
ltr
,
layoutDirection:
TextDirection
.
ltr
,
...
...
packages/flutter_test/lib/src/test_pointer.dart
View file @
60a1b2b9
...
@@ -22,15 +22,9 @@ class TestPointer {
...
@@ -22,15 +22,9 @@ class TestPointer {
///
///
/// Multiple [TestPointer]s created with the same pointer identifier will
/// Multiple [TestPointer]s created with the same pointer identifier will
/// interfere with each other if they are used in parallel.
/// interfere with each other if they are used in parallel.
TestPointer
([
TestPointer
([
this
.
pointer
=
1
,
this
.
kind
=
PointerDeviceKind
.
touch
])
this
.
pointer
=
1
,
this
.
kind
=
PointerDeviceKind
.
touch
,
int
buttons
=
kPrimaryButton
,
])
:
assert
(
kind
!=
null
),
:
assert
(
kind
!=
null
),
assert
(
pointer
!=
null
),
assert
(
pointer
!=
null
);
assert
(
buttons
!=
null
),
_buttons
=
buttons
;
/// The pointer identifier used for events generated by this object.
/// The pointer identifier used for events generated by this object.
///
///
...
@@ -41,11 +35,6 @@ class TestPointer {
...
@@ -41,11 +35,6 @@ class TestPointer {
/// [PointerDeviceKind.touch].
/// [PointerDeviceKind.touch].
final
PointerDeviceKind
kind
;
final
PointerDeviceKind
kind
;
/// The kind of buttons to simulate on Down and Move events. Defaults to
/// [kPrimaryButton].
int
get
buttons
=>
_buttons
;
int
_buttons
;
/// Whether the pointer simulated by this object is currently down.
/// Whether the pointer simulated by this object is currently down.
///
///
/// A pointer is released (goes up) by calling [up] or [cancel].
/// A pointer is released (goes up) by calling [up] or [cancel].
...
@@ -62,14 +51,8 @@ class TestPointer {
...
@@ -62,14 +51,8 @@ class TestPointer {
/// If a custom event is created outside of this class, this function is used
/// If a custom event is created outside of this class, this function is used
/// to set the [isDown].
/// to set the [isDown].
bool
setDownInfo
(
bool
setDownInfo
(
PointerEvent
event
,
Offset
newLocation
)
{
PointerEvent
event
,
Offset
newLocation
,
{
int
buttons
,
})
{
_location
=
newLocation
;
_location
=
newLocation
;
if
(
buttons
!=
null
)
_buttons
=
buttons
;
switch
(
event
.
runtimeType
)
{
switch
(
event
.
runtimeType
)
{
case
PointerDownEvent:
case
PointerDownEvent:
assert
(!
isDown
);
assert
(!
isDown
);
...
@@ -89,25 +72,15 @@ class TestPointer {
...
@@ -89,25 +72,15 @@ class TestPointer {
///
///
/// By default, the time stamp on the event is [Duration.zero]. You can give a
/// By default, the time stamp on the event is [Duration.zero]. You can give a
/// specific time stamp by passing the `timeStamp` argument.
/// specific time stamp by passing the `timeStamp` argument.
///
PointerDownEvent
down
(
Offset
newLocation
,
{
Duration
timeStamp
=
Duration
.
zero
})
{
/// By default, the set of buttons in the last down or move event is used.
/// You can give a specific set of buttons by passing the `buttons` argument.
PointerDownEvent
down
(
Offset
newLocation
,
{
Duration
timeStamp
=
Duration
.
zero
,
int
buttons
,
})
{
assert
(!
isDown
);
assert
(!
isDown
);
_isDown
=
true
;
_isDown
=
true
;
_location
=
newLocation
;
_location
=
newLocation
;
if
(
buttons
!=
null
)
_buttons
=
buttons
;
return
PointerDownEvent
(
return
PointerDownEvent
(
timeStamp:
timeStamp
,
timeStamp:
timeStamp
,
kind:
kind
,
kind:
kind
,
pointer:
pointer
,
pointer:
pointer
,
position:
location
,
position:
location
,
buttons:
_buttons
,
);
);
}
}
...
@@ -118,14 +91,7 @@ class TestPointer {
...
@@ -118,14 +91,7 @@ class TestPointer {
///
///
/// [isDown] must be true when this is called, since move events can only
/// [isDown] must be true when this is called, since move events can only
/// be generated when the pointer is down.
/// be generated when the pointer is down.
///
PointerMoveEvent
move
(
Offset
newLocation
,
{
Duration
timeStamp
=
Duration
.
zero
})
{
/// By default, the set of buttons in the last down or move event is used.
/// You can give a specific set of buttons by passing the `buttons` argument.
PointerMoveEvent
move
(
Offset
newLocation
,
{
Duration
timeStamp
=
Duration
.
zero
,
int
buttons
,
})
{
assert
(
assert
(
isDown
,
isDown
,
'Move events can only be generated when the pointer is down. To '
'Move events can only be generated when the pointer is down. To '
...
@@ -133,15 +99,12 @@ class TestPointer {
...
@@ -133,15 +99,12 @@ class TestPointer {
'up, use hover() instead.'
);
'up, use hover() instead.'
);
final
Offset
delta
=
newLocation
-
location
;
final
Offset
delta
=
newLocation
-
location
;
_location
=
newLocation
;
_location
=
newLocation
;
if
(
buttons
!=
null
)
_buttons
=
buttons
;
return
PointerMoveEvent
(
return
PointerMoveEvent
(
timeStamp:
timeStamp
,
timeStamp:
timeStamp
,
kind:
kind
,
kind:
kind
,
pointer:
pointer
,
pointer:
pointer
,
position:
newLocation
,
position:
newLocation
,
delta:
delta
,
delta:
delta
,
buttons:
_buttons
,
);
);
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment