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
81b3bdd4
Commit
81b3bdd4
authored
Aug 28, 2015
by
Adam Barth
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #930 from abarth/scroll
Add scroll gestures and use them in Scrollable
parents
9047830c
e99ff362
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
245 additions
and
40 deletions
+245
-40
recognizer.dart
packages/flutter/lib/gestures/recognizer.dart
+4
-5
scroll.dart
packages/flutter/lib/gestures/scroll.dart
+76
-0
show_press.dart
packages/flutter/lib/gestures/show_press.dart
+0
-1
tap.dart
packages/flutter/lib/gestures/tap.dart
+0
-1
gesture_detector.dart
packages/flutter/lib/widgets/gesture_detector.dart
+33
-2
scrollable.dart
packages/flutter/lib/widgets/scrollable.dart
+15
-18
scroll_test.dart
packages/unit/test/gestures/scroll_test.dart
+91
-0
widget_tester.dart
packages/unit/test/widget/widget_tester.dart
+26
-13
No files found.
packages/flutter/lib/gestures/recognizer.dart
View file @
81b3bdd4
...
...
@@ -9,6 +9,8 @@ import 'package:sky/base/pointer_router.dart';
import
'package:sky/gestures/arena.dart'
;
import
'package:sky/gestures/constants.dart'
;
export
'package:sky/base/pointer_router.dart'
show
PointerRouter
;
abstract
class
GestureRecognizer
extends
GestureArenaMember
{
GestureRecognizer
({
PointerRouter
router
})
:
_router
=
router
;
...
...
@@ -21,8 +23,8 @@ abstract class GestureRecognizer extends GestureArenaMember {
void
addPointer
(
sky
.
PointerEvent
event
);
void
handleEvent
(
sky
.
PointerEvent
event
);
void
acceptGesture
(
int
key
);
void
rejectGesture
(
int
key
);
void
acceptGesture
(
int
pointer
)
{
}
void
rejectGesture
(
int
pointer
)
{
}
void
didStopTrackingLastPointer
();
void
resolve
(
GestureDisposition
disposition
)
{
...
...
@@ -115,9 +117,6 @@ abstract class PrimaryPointerGestureRecognizer extends GestureRecognizer {
assert
(
deadline
==
null
);
}
void
acceptGesture
(
int
pointer
)
{
}
void
rejectGesture
(
int
pointer
)
{
_stopTimer
();
if
(
pointer
==
primaryPointer
)
...
...
packages/flutter/lib/gestures/scroll.dart
0 → 100644
View file @
81b3bdd4
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'dart:sky'
as
sky
;
import
'package:sky/gestures/arena.dart'
;
import
'package:sky/gestures/recognizer.dart'
;
import
'package:sky/gestures/constants.dart'
;
enum
ScrollState
{
ready
,
possible
,
accepted
}
typedef
void
GestureScrollStartCallback
(
sky
.
Offset
scrollDelta
);
typedef
void
GestureScrollUpdateCallback
(
sky
.
Offset
scrollDelta
);
typedef
void
GestureScrollEndCallback
(
);
sky
.
Offset
_getScrollOffset
(
sky
.
PointerEvent
event
)
{
// Notice that we negate dy because scroll offsets go in the opposite direction.
return
new
sky
.
Offset
(
event
.
dx
,
-
event
.
dy
);
}
class
ScrollGestureRecognizer
extends
GestureRecognizer
{
ScrollGestureRecognizer
({
PointerRouter
router
,
this
.
onScrollStart
,
this
.
onScrollUpdate
,
this
.
onScrollEnd
})
:
super
(
router:
router
);
GestureScrollStartCallback
onScrollStart
;
GestureScrollUpdateCallback
onScrollUpdate
;
GestureScrollEndCallback
onScrollEnd
;
ScrollState
state
=
ScrollState
.
ready
;
sky
.
Offset
pendingScrollOffset
;
void
addPointer
(
sky
.
PointerEvent
event
)
{
startTrackingPointer
(
event
.
pointer
);
if
(
state
==
ScrollState
.
ready
)
{
state
=
ScrollState
.
possible
;
pendingScrollOffset
=
sky
.
Offset
.
zero
;
}
}
void
handleEvent
(
sky
.
PointerEvent
event
)
{
assert
(
state
!=
ScrollState
.
ready
);
if
(
event
.
type
==
'pointermove'
)
{
sky
.
Offset
offset
=
_getScrollOffset
(
event
);
if
(
state
==
ScrollState
.
accepted
)
{
onScrollUpdate
(
offset
);
}
else
{
pendingScrollOffset
+=
offset
;
if
(
pendingScrollOffset
.
distance
>
kTouchSlop
)
resolve
(
GestureDisposition
.
accepted
);
}
}
stopTrackingIfPointerNoLongerDown
(
event
);
}
void
acceptGesture
(
int
pointer
)
{
if
(
state
!=
ScrollState
.
accepted
)
{
state
=
ScrollState
.
accepted
;
sky
.
Offset
offset
=
pendingScrollOffset
;
pendingScrollOffset
=
null
;
onScrollStart
(
offset
);
}
}
void
didStopTrackingLastPointer
()
{
bool
wasAccepted
=
(
state
==
ScrollState
.
accepted
);
state
=
ScrollState
.
ready
;
if
(
wasAccepted
)
onScrollEnd
();
}
}
packages/flutter/lib/gestures/show_press.dart
View file @
81b3bdd4
...
...
@@ -4,7 +4,6 @@
import
'dart:sky'
as
sky
;
import
'package:sky/base/pointer_router.dart'
;
import
'package:sky/gestures/arena.dart'
;
import
'package:sky/gestures/constants.dart'
;
import
'package:sky/gestures/recognizer.dart'
;
...
...
packages/flutter/lib/gestures/tap.dart
View file @
81b3bdd4
...
...
@@ -4,7 +4,6 @@
import
'dart:sky'
as
sky
;
import
'package:sky/base/pointer_router.dart'
;
import
'package:sky/gestures/arena.dart'
;
import
'package:sky/gestures/recognizer.dart'
;
...
...
packages/flutter/lib/widgets/gesture_detector.dart
View file @
81b3bdd4
...
...
@@ -4,9 +4,9 @@
import
'dart:sky'
as
sky
;
import
'package:sky/base/pointer_router.dart'
;
import
'package:sky/gestures/long_press.dart'
;
import
'package:sky/gestures/recognizer.dart'
;
import
'package:sky/gestures/scroll.dart'
;
import
'package:sky/gestures/show_press.dart'
;
import
'package:sky/gestures/tap.dart'
;
import
'package:sky/rendering/sky_binding.dart'
;
...
...
@@ -18,19 +18,28 @@ class GestureDetector extends StatefulComponent {
this
.
child
,
this
.
onTap
,
this
.
onShowPress
,
this
.
onLongPress
this
.
onLongPress
,
this
.
onScrollStart
,
this
.
onScrollUpdate
,
this
.
onScrollEnd
})
:
super
(
key:
key
);
Widget
child
;
GestureTapListener
onTap
;
GestureShowPressListener
onShowPress
;
GestureLongPressListener
onLongPress
;
GestureScrollStartCallback
onScrollStart
;
GestureScrollUpdateCallback
onScrollUpdate
;
GestureScrollEndCallback
onScrollEnd
;
void
syncConstructorArguments
(
GestureDetector
source
)
{
child
=
source
.
child
;
onTap
=
source
.
onTap
;
onShowPress
=
source
.
onShowPress
;
onLongPress
=
source
.
onLongPress
;
onScrollStart
=
source
.
onScrollStart
;
onScrollUpdate
=
source
.
onScrollUpdate
;
onScrollEnd
=
source
.
onScrollEnd
;
_syncGestureListeners
();
}
...
...
@@ -57,6 +66,13 @@ class GestureDetector extends StatefulComponent {
return
_longPress
;
}
ScrollGestureRecognizer
_scroll
;
ScrollGestureRecognizer
_ensureScroll
()
{
if
(
_scroll
==
null
)
_scroll
=
new
ScrollGestureRecognizer
(
router:
_router
);
return
_scroll
;
}
void
didMount
()
{
super
.
didMount
();
_syncGestureListeners
();
...
...
@@ -67,12 +83,14 @@ class GestureDetector extends StatefulComponent {
_tap
=
_ensureDisposed
(
_tap
);
_showPress
=
_ensureDisposed
(
_showPress
);
_longPress
=
_ensureDisposed
(
_longPress
);
_scroll
=
_ensureDisposed
(
_scroll
);
}
void
_syncGestureListeners
()
{
_syncTap
();
_syncShowPress
();
_syncLongPress
();
_syncScroll
();
}
void
_syncTap
()
{
...
...
@@ -96,6 +114,17 @@ class GestureDetector extends StatefulComponent {
_ensureLongPress
().
onLongPress
=
onLongPress
;
}
void
_syncScroll
()
{
if
(
onScrollStart
==
null
&&
onScrollUpdate
==
null
&&
onScrollEnd
==
null
)
{
_scroll
=
_ensureDisposed
(
_scroll
);
}
else
{
_ensureScroll
()
..
onScrollStart
=
onScrollStart
..
onScrollUpdate
=
onScrollUpdate
..
onScrollEnd
=
onScrollEnd
;
}
}
GestureRecognizer
_ensureDisposed
(
GestureRecognizer
recognizer
)
{
if
(
recognizer
!=
null
)
recognizer
.
dispose
();
...
...
@@ -109,6 +138,8 @@ class GestureDetector extends StatefulComponent {
_showPress
.
addPointer
(
event
);
if
(
_longPress
!=
null
)
_longPress
.
addPointer
(
event
);
if
(
_scroll
!=
null
)
_scroll
.
addPointer
(
event
);
return
EventDisposition
.
processed
;
}
...
...
packages/flutter/lib/widgets/scrollable.dart
View file @
81b3bdd4
...
...
@@ -8,8 +8,8 @@ import 'dart:sky' as sky;
import
'package:newton/newton.dart'
;
import
'package:sky/animation/animated_simulation.dart'
;
import
'package:sky/animation/animation_performance.dart'
;
import
'package:sky/animation/animated_value.dart'
;
import
'package:sky/animation/animation_performance.dart'
;
import
'package:sky/animation/curves.dart'
;
import
'package:sky/animation/scroll_behavior.dart'
;
import
'package:sky/gestures/constants.dart'
;
...
...
@@ -17,6 +17,7 @@ import 'package:sky/rendering/box.dart';
import
'package:sky/rendering/viewport.dart'
;
import
'package:sky/widgets/basic.dart'
;
import
'package:sky/widgets/framework.dart'
;
import
'package:sky/widgets/gesture_detector.dart'
;
import
'package:sky/widgets/mixed_viewport.dart'
;
import
'package:sky/widgets/scrollable.dart'
;
...
...
@@ -83,15 +84,17 @@ abstract class Scrollable extends StatefulComponent {
Widget
buildContent
();
Widget
build
()
{
return
new
Listener
(
child:
buildContent
(),
onPointerDown:
_handlePointerDown
,
onPointerUp:
_handlePointerUpOrCancel
,
onPointerCancel:
_handlePointerUpOrCancel
,
onGestureFlingStart:
_handleFlingStart
,
onGestureFlingCancel:
_handleFlingCancel
,
onGestureScrollUpdate:
_handleScrollUpdate
,
onWheel:
_handleWheel
return
new
GestureDetector
(
onScrollStart:
_handleScrollOffset
,
onScrollUpdate:
_handleScrollOffset
,
onScrollEnd:
_maybeSettleScrollOffset
,
child:
new
Listener
(
child:
buildContent
(),
onPointerDown:
_handlePointerDown
,
onGestureFlingStart:
_handleFlingStart
,
onGestureFlingCancel:
_handleFlingCancel
,
onWheel:
_handleWheel
)
);
}
...
...
@@ -171,9 +174,8 @@ abstract class Scrollable extends StatefulComponent {
return
EventDisposition
.
processed
;
}
EventDisposition
_handleScrollUpdate
(
sky
.
GestureEvent
event
)
{
scrollBy
(
scrollDirection
==
ScrollDirection
.
horizontal
?
event
.
dx
:
-
event
.
dy
);
return
EventDisposition
.
processed
;
void
_handleScrollOffset
(
Offset
offset
)
{
scrollBy
(
scrollDirection
==
ScrollDirection
.
horizontal
?
offset
.
dx
:
offset
.
dy
);
}
EventDisposition
_handleFlingStart
(
sky
.
GestureEvent
event
)
{
...
...
@@ -187,11 +189,6 @@ abstract class Scrollable extends StatefulComponent {
settleScrollOffset
();
}
EventDisposition
_handlePointerUpOrCancel
(
_
)
{
_maybeSettleScrollOffset
();
return
EventDisposition
.
processed
;
}
EventDisposition
_handleFlingCancel
(
sky
.
GestureEvent
event
)
{
_maybeSettleScrollOffset
();
return
EventDisposition
.
processed
;
...
...
packages/unit/test/gestures/scroll_test.dart
0 → 100644
View file @
81b3bdd4
import
'dart:sky'
as
sky
;
import
'package:sky/base/pointer_router.dart'
;
import
'package:sky/gestures/scroll.dart'
;
import
'package:test/test.dart'
;
import
'../engine/mock_events.dart'
;
TestPointerEvent
down
=
new
TestPointerEvent
(
pointer:
5
,
type:
'pointerdown'
,
x:
10.0
,
y:
10.0
);
TestPointerEvent
move1
=
new
TestPointerEvent
(
pointer:
5
,
type:
'pointermove'
,
x:
20.0
,
y:
20.0
,
dx:
10.0
,
dy:
10.0
);
TestPointerEvent
move2
=
new
TestPointerEvent
(
pointer:
5
,
type:
'pointermove'
,
x:
20.0
,
y:
25.0
,
dx:
0.0
,
dy:
5.0
);
TestPointerEvent
up
=
new
TestPointerEvent
(
pointer:
5
,
type:
'pointerup'
,
x:
20.0
,
y:
25.0
);
void
main
(
)
{
test
(
'Should recognize scroll'
,
()
{
PointerRouter
router
=
new
PointerRouter
();
ScrollGestureRecognizer
scroll
=
new
ScrollGestureRecognizer
(
router:
router
);
sky
.
Offset
startOffset
;
scroll
.
onScrollStart
=
(
sky
.
Offset
offset
)
{
startOffset
=
offset
;
};
sky
.
Offset
updateOffset
;
scroll
.
onScrollUpdate
=
(
sky
.
Offset
offset
)
{
updateOffset
=
offset
;
};
bool
didEndScroll
=
false
;
scroll
.
onScrollEnd
=
()
{
didEndScroll
=
true
;
};
scroll
.
addPointer
(
down
);
expect
(
startOffset
,
isNull
);
expect
(
updateOffset
,
isNull
);
expect
(
didEndScroll
,
isFalse
);
router
.
handleEvent
(
down
,
null
);
expect
(
startOffset
,
isNull
);
expect
(
updateOffset
,
isNull
);
expect
(
didEndScroll
,
isFalse
);
router
.
handleEvent
(
move1
,
null
);
expect
(
startOffset
,
new
sky
.
Offset
(
10.0
,
-
10.0
));
startOffset
=
null
;
expect
(
updateOffset
,
isNull
);
expect
(
didEndScroll
,
isFalse
);
router
.
handleEvent
(
move2
,
null
);
expect
(
startOffset
,
isNull
);
expect
(
updateOffset
,
new
sky
.
Offset
(
0.0
,
-
5.0
));
updateOffset
=
null
;
expect
(
didEndScroll
,
isFalse
);
router
.
handleEvent
(
up
,
null
);
expect
(
startOffset
,
isNull
);
expect
(
updateOffset
,
isNull
);
expect
(
didEndScroll
,
isTrue
);
didEndScroll
=
false
;
scroll
.
dispose
();
});
}
packages/unit/test/widget/widget_tester.dart
View file @
81b3bdd4
...
...
@@ -83,26 +83,39 @@ class WidgetTester {
return
box
.
localToGlobal
(
box
.
size
.
center
(
Point
.
origin
));
}
HitTestResult
_hitTest
(
Point
location
)
=>
SkyBinding
.
instance
.
hitTest
(
location
);
EventDisposition
_dispatchEvent
(
sky
.
Event
event
,
HitTestResult
result
)
{
return
SkyBinding
.
instance
.
dispatchEvent
(
event
,
result
);
}
void
tap
(
Widget
widget
)
{
Point
location
=
getCenter
(
widget
);
dispatchEvent
(
new
TestPointerEvent
(
type:
'pointerdown'
,
x:
location
.
x
,
y:
location
.
y
),
location
);
dispatchEvent
(
new
TestPointerEvent
(
type:
'pointerup'
,
x:
location
.
x
,
y:
location
.
y
),
location
);
HitTestResult
result
=
_hitTest
(
location
);
_dispatchEvent
(
new
TestPointerEvent
(
type:
'pointerdown'
,
x:
location
.
x
,
y:
location
.
y
),
result
);
_dispatchEvent
(
new
TestPointerEvent
(
type:
'pointerup'
,
x:
location
.
x
,
y:
location
.
y
),
result
);
}
void
scroll
(
Widget
widget
,
Offset
offset
)
{
dispatchEvent
(
new
TestGestureEvent
(
type:
'gesturescrollstart'
),
getCenter
(
widget
));
dispatchEvent
(
new
TestGestureEvent
(
type:
'gesturescrollupdate'
,
dx:
offset
.
dx
,
dy:
offset
.
dy
),
getCenter
(
widget
));
// pointerup to trigger scroll settling in Scrollable<T>
dispatchEvent
(
new
TestPointerEvent
(
type:
'pointerup'
,
down:
false
,
primary:
true
),
getCenter
(
widget
));
Point
startLocation
=
getCenter
(
widget
);
HitTestResult
result
=
_hitTest
(
startLocation
);
_dispatchEvent
(
new
TestPointerEvent
(
type:
'pointerdown'
,
x:
startLocation
.
x
,
y:
startLocation
.
y
),
result
);
Point
endLocation
=
startLocation
+
offset
;
_dispatchEvent
(
new
TestPointerEvent
(
type:
'pointermove'
,
x:
endLocation
.
x
,
y:
endLocation
.
y
,
dx:
offset
.
dx
,
dy:
offset
.
dy
),
result
);
_dispatchEvent
(
new
TestPointerEvent
(
type:
'pointerup'
,
x:
endLocation
.
x
,
y:
endLocation
.
y
),
result
);
}
void
dispatchEvent
(
sky
.
Event
event
,
Point
position
)
{
HitTestResult
result
=
SkyBinding
.
instance
.
hitTest
(
position
);
SkyBinding
.
instance
.
dispatchEvent
(
event
,
result
);
void
dispatchEvent
(
sky
.
Event
event
,
Point
location
)
{
_dispatchEvent
(
event
,
_hitTest
(
location
));
}
void
pumpFrame
(
WidgetBuilder
builder
,
[
double
frameTimeMs
=
0.0
])
{
...
...
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