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
f50fe13f
Commit
f50fe13f
authored
May 19, 2017
by
Ian Hickson
Committed by
GitHub
May 19, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix flip-flop behaviour with two competing taps (#10151)
parent
ee1db835
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
91 additions
and
8 deletions
+91
-8
recognizer.dart
packages/flutter/lib/src/gestures/recognizer.dart
+11
-2
tap.dart
packages/flutter/lib/src/gestures/tap.dart
+9
-6
tap_test.dart
packages/flutter/test/gestures/tap_test.dart
+71
-0
No files found.
packages/flutter/lib/src/gestures/recognizer.dart
View file @
f50fe13f
...
...
@@ -58,6 +58,8 @@ abstract class GestureRecognizer extends GestureArenaMember {
/// Invoke a callback provided by the application, catching and logging any
/// exceptions.
///
/// The `name` argument is ignored except when reporting exceptions.
@protected
T
invokeCallback
<
T
>(
String
name
,
RecognizerCallback
<
T
>
callback
)
{
T
result
;
...
...
@@ -78,6 +80,9 @@ abstract class GestureRecognizer extends GestureArenaMember {
}
return
result
;
}
@override
String
toString
()
=>
'
$runtimeType
#
$hashCode
'
;
}
/// Base class for gesture recognizers that can only recognize one
...
...
@@ -109,7 +114,8 @@ abstract class OneSequenceGestureRecognizer extends GestureRecognizer {
@protected
void
didStopTrackingLastPointer
(
int
pointer
);
/// Resolves this recognizer's participation in each gesture arena with the given disposition.
/// Resolves this recognizer's participation in each gesture arena with the
/// given disposition.
@protected
@mustCallSuper
void
resolve
(
GestureDisposition
disposition
)
{
...
...
@@ -277,7 +283,7 @@ abstract class PrimaryPointerGestureRecognizer extends OneSequenceGestureRecogni
@override
void
rejectGesture
(
int
pointer
)
{
if
(
pointer
==
primaryPointer
)
{
if
(
pointer
==
primaryPointer
&&
state
==
GestureRecognizerState
.
possible
)
{
_stopTimer
();
state
=
GestureRecognizerState
.
defunct
;
}
...
...
@@ -285,6 +291,7 @@ abstract class PrimaryPointerGestureRecognizer extends OneSequenceGestureRecogni
@override
void
didStopTrackingLastPointer
(
int
pointer
)
{
assert
(
state
!=
GestureRecognizerState
.
ready
);
_stopTimer
();
state
=
GestureRecognizerState
.
ready
;
}
...
...
@@ -307,4 +314,6 @@ abstract class PrimaryPointerGestureRecognizer extends OneSequenceGestureRecogni
return
offset
.
distance
;
}
@override
String
toString
()
=>
'
$runtimeType
#
$hashCode
(
$state
)'
;
}
packages/flutter/lib/src/gestures/tap.dart
View file @
f50fe13f
...
...
@@ -98,8 +98,10 @@ class TapGestureRecognizer extends PrimaryPointerGestureRecognizer {
@override
void
resolve
(
GestureDisposition
disposition
)
{
if
(
_wonArenaForPrimaryPointer
&&
disposition
==
GestureDisposition
.
rejected
)
{
// This can happen if the superclass decides the primary pointer
// exceeded the touch slop, or if the recognizer is disposed.
if
(
onTapCancel
!=
null
)
invokeCallback
<
Null
>(
'
onTapCancel'
,
onTapCancel
);
// ignore: STRONG_MODE_INVALID_CAST_FUNCTION_EXPR, https://github.com/dart-lang/sdk/issues/27504
invokeCallback
<
Null
>(
'
spontaneous onTapCancel'
,
onTapCancel
);
_reset
();
}
super
.
resolve
(
disposition
);
...
...
@@ -124,9 +126,10 @@ class TapGestureRecognizer extends PrimaryPointerGestureRecognizer {
void
rejectGesture
(
int
pointer
)
{
super
.
rejectGesture
(
pointer
);
if
(
pointer
==
primaryPointer
)
{
assert
(
state
==
GestureRecognizerState
.
defunct
);
// Another gesture won the arena.
assert
(
state
!=
GestureRecognizerState
.
possible
);
if
(
onTapCancel
!=
null
)
invokeCallback
<
Null
>(
'
onTapCancel'
,
onTapCancel
);
// ignore: STRONG_MODE_INVALID_CAST_FUNCTION_EXPR, https://github.com/dart-lang/sdk/issues/27504
invokeCallback
<
Null
>(
'
forced onTapCancel'
,
onTapCancel
);
_reset
();
}
}
...
...
@@ -134,7 +137,7 @@ class TapGestureRecognizer extends PrimaryPointerGestureRecognizer {
void
_checkDown
()
{
if
(!
_sentTapDown
)
{
if
(
onTapDown
!=
null
)
invokeCallback
<
Null
>(
'onTapDown'
,
()
=>
onTapDown
(
new
TapDownDetails
(
globalPosition:
initialPosition
)));
// ignore: STRONG_MODE_INVALID_CAST_FUNCTION_EXPR, https://github.com/dart-lang/sdk/issues/27504
invokeCallback
<
Null
>(
'onTapDown'
,
()
{
onTapDown
(
new
TapDownDetails
(
globalPosition:
initialPosition
));
});
_sentTapDown
=
true
;
}
}
...
...
@@ -143,9 +146,9 @@ class TapGestureRecognizer extends PrimaryPointerGestureRecognizer {
if
(
_wonArenaForPrimaryPointer
&&
_finalPosition
!=
null
)
{
resolve
(
GestureDisposition
.
accepted
);
if
(
onTapUp
!=
null
)
invokeCallback
<
Null
>(
'onTapUp'
,
()
=>
onTapUp
(
new
TapUpDetails
(
globalPosition:
_finalPosition
)));
// ignore: STRONG_MODE_INVALID_CAST_FUNCTION_EXPR, https://github.com/dart-lang/sdk/issues/27504
invokeCallback
<
Null
>(
'onTapUp'
,
()
{
onTapUp
(
new
TapUpDetails
(
globalPosition:
_finalPosition
));
});
if
(
onTap
!=
null
)
invokeCallback
<
Null
>(
'onTap'
,
onTap
);
// ignore: STRONG_MODE_INVALID_CAST_FUNCTION_EXPR, https://github.com/dart-lang/sdk/issues/27504
invokeCallback
<
Null
>(
'onTap'
,
onTap
);
_reset
();
}
}
...
...
packages/flutter/test/gestures/tap_test.dart
View file @
f50fe13f
...
...
@@ -284,4 +284,75 @@ void main() {
FlutterError
.
onError
=
previousErrorHandler
;
tap
.
dispose
();
});
testGesture
(
'No duplicate tap events'
,
(
GestureTester
tester
)
{
final
TapGestureRecognizer
tapA
=
new
TapGestureRecognizer
();
final
TapGestureRecognizer
tapB
=
new
TapGestureRecognizer
();
final
List
<
String
>
log
=
<
String
>[];
tapA
.
onTapDown
=
(
TapDownDetails
details
)
{
log
.
add
(
'tapA onTapDown'
);
};
tapA
.
onTapUp
=
(
TapUpDetails
details
)
{
log
.
add
(
'tapA onTapUp'
);
};
tapA
.
onTap
=
()
{
log
.
add
(
'tapA onTap'
);
};
tapA
.
onTapCancel
=
()
{
log
.
add
(
'tapA onTapCancel'
);
};
tapB
.
onTapDown
=
(
TapDownDetails
details
)
{
log
.
add
(
'tapB onTapDown'
);
};
tapB
.
onTapUp
=
(
TapUpDetails
details
)
{
log
.
add
(
'tapB onTapUp'
);
};
tapB
.
onTap
=
()
{
log
.
add
(
'tapB onTap'
);
};
tapB
.
onTapCancel
=
()
{
log
.
add
(
'tapB onTapCancel'
);
};
log
.
add
(
'start'
);
tapA
.
addPointer
(
down1
);
log
.
add
(
'added 1 to A'
);
tapB
.
addPointer
(
down1
);
log
.
add
(
'added 1 to B'
);
tester
.
closeArena
(
1
);
log
.
add
(
'closed 1'
);
tester
.
route
(
down1
);
log
.
add
(
'routed 1 down'
);
tester
.
route
(
up1
);
log
.
add
(
'routed 1 up'
);
GestureBinding
.
instance
.
gestureArena
.
sweep
(
1
);
log
.
add
(
'swept 1'
);
tapA
.
addPointer
(
down2
);
log
.
add
(
'down 2 to A'
);
tapB
.
addPointer
(
down2
);
log
.
add
(
'down 2 to B'
);
tester
.
closeArena
(
2
);
log
.
add
(
'closed 2'
);
tester
.
route
(
down2
);
log
.
add
(
'routed 2 down'
);
tester
.
route
(
up2
);
log
.
add
(
'routed 2 up'
);
GestureBinding
.
instance
.
gestureArena
.
sweep
(
2
);
log
.
add
(
'swept 2'
);
tapA
.
dispose
();
log
.
add
(
'disposed A'
);
tapB
.
dispose
();
log
.
add
(
'disposed B'
);
expect
(
log
,
<
String
>[
'start'
,
'added 1 to A'
,
'added 1 to B'
,
'closed 1'
,
'routed 1 down'
,
'routed 1 up'
,
'tapA onTapDown'
,
'tapA onTapUp'
,
'tapA onTap'
,
'tapB onTapCancel'
,
'swept 1'
,
'down 2 to A'
,
'down 2 to B'
,
'closed 2'
,
'routed 2 down'
,
'routed 2 up'
,
'tapA onTapDown'
,
'tapA onTapUp'
,
'tapA onTap'
,
'tapB onTapCancel'
,
'swept 2'
,
'disposed A'
,
'disposed B'
,
]);
});
}
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