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
91a3ac95
Commit
91a3ac95
authored
Mar 03, 2016
by
Hixie
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Reorder and document members in ScrollableState
parent
932b09c3
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
254 additions
and
160 deletions
+254
-160
scrollable.dart
packages/flutter/lib/src/widgets/scrollable.dart
+254
-160
No files found.
packages/flutter/lib/src/widgets/scrollable.dart
View file @
91a3ac95
...
...
@@ -55,6 +55,31 @@ abstract class Scrollable extends StatefulComponent {
/// The axis along which this widget should scroll.
final
Axis
scrollDirection
;
/// Whether to place first child at the start of the container or
/// the last child at the end of the container, when the scrollable
/// has not been scrolled and has no initial scroll offset.
///
/// For example, if the [scrollDirection] is [Axis.vertical] and
/// there are enough items to overflow the container, then
/// [ViewportAnchor.start] means that the top of the first item
/// should be aligned with the top of the scrollable with the last
/// item below the bottom, and [ViewportAnchor.end] means the bottom
/// of the last item should be aligned with the bottom of the
/// scrollable, with the first item above the top.
///
/// This also affects whether, when an item is added or removed, the
/// displacement will be towards the first item or the last item.
/// Continuing the earlier example, if a new item is inserted in the
/// middle of the list, in the [ViewportAnchor.start] case the items
/// after it (with greater indices, down to the item with the
/// highest index) will be pushed down, while in the
/// [ViewportAnchor.end] case the items before it (with lower
/// indices, up to the item with the index 0) will be pushed up.
///
/// Subclasses may ignore this value if, for instance, they do not
/// have a concept of an anchor, or have more complicated behavior
/// (e.g. they would by default put the middle item in the middle of
/// the container).
final
ViewportAnchor
scrollAnchor
;
/// Called whenever this widget starts to scroll.
...
...
@@ -153,10 +178,44 @@ abstract class Scrollable extends StatefulComponent {
ScrollableState
createState
();
}
/// Contains the state for common scrolling
behavior
s.
/// Contains the state for common scrolling
widget
s.
///
/// Widgets that subclass [Scrollable] typically use state objects that subclass
/// [ScrollableState].
/// Widgets that subclass [Scrollable] typically use state objects
/// that subclass [ScrollableState].
///
/// The main state of a ScrollableState is the "scroll offset", which
/// is the the logical description of the current scroll position and
/// is stored in [scrollOffset] as a double. The units of the scroll
/// offset are defined by the specific subclass. By default, the units
/// are logical pixels.
///
/// A "pixel offset" is a distance in logical pixels (or a velocity in
/// logical pixels per second). The pixel offset corresponding to the
/// current scroll position is typically used as the paint offset
/// argument to the underlying [Viewport] class (or equivalent); see
/// the [buildContent] method.
///
/// A "pixel delta" is an [Offset] that describes a two-dimensional
/// distance as reported by input events. If the scrolling convention
/// is axis-aligned (as in a vertical scrolling list or a horizontal
/// scrolling list), then the pixel delta will consist of a pixel
/// offset in the scroll axis, and a value in the other axis that is
/// either ignored (when converting to a scroll offset) or set to zero
/// (when converting a scroll offset to a pixel delta).
///
/// If the units of the scroll offset are not logical pixels, then a
/// mapping must be made from logical pixels (as used by incoming
/// input events) and the scroll offset (as stored internally). To
/// provide this mapping, override the [pixelOffsetToScrollOffset] and
/// [scrollOffsetToPixelOffset] methods.
///
/// If the scrollable is not providing axis-aligned scrolling, then,
/// to convert pixel deltas to scroll offsets and vice versa, override
/// the [pixelDeltaToScrollOffset] and [scrollOffsetToPixelOffset]
/// methods. By default, these assume an axis-aligned scroll behavior
/// along the [config.scrollDirection] axis and are implemented in
/// terms of the [pixelOffsetToScrollOffset] and
/// [scrollOffsetToPixelOffset] methods.
abstract
class
ScrollableState
<
T
extends
Scrollable
>
extends
State
<
T
>
{
void
initState
()
{
super
.
initState
();
...
...
@@ -166,6 +225,11 @@ abstract class ScrollableState<T extends Scrollable> extends State<T> {
AnimationController
_controller
;
void
dispose
()
{
_controller
.
stop
();
super
.
dispose
();
}
/// The current scroll offset.
///
/// The scroll offset is applied to the child widget along the scroll
...
...
@@ -178,6 +242,8 @@ abstract class ScrollableState<T extends Scrollable> extends State<T> {
/// Scrollable gesture handlers convert their incoming values with this method.
/// Subclasses that define scrollOffset in units other than pixels must
/// override this method.
///
/// This function should be the inverse of [scrollOffsetToPixelOffset].
double
pixelOffsetToScrollOffset
(
double
pixelOffset
)
{
switch
(
config
.
scrollAnchor
)
{
case
ViewportAnchor
.
start
:
...
...
@@ -189,6 +255,9 @@ abstract class ScrollableState<T extends Scrollable> extends State<T> {
}
}
/// Convert a scrollOffset value to the number of pixels to which it corresponds.
///
/// This function should be the inverse of [pixelOffsetToScrollOffset].
double
scrollOffsetToPixelOffset
(
double
scrollOffset
)
{
switch
(
config
.
scrollAnchor
)
{
case
ViewportAnchor
.
start
:
...
...
@@ -200,6 +269,9 @@ abstract class ScrollableState<T extends Scrollable> extends State<T> {
/// Returns the scroll offset component of the given pixel delta, accounting
/// for the scroll direction and scroll anchor.
///
/// A pixel delta is an [Offset] in pixels. Typically this function
/// is implemented in terms of [pixelOffsetToScrollOffset].
double
pixelDeltaToScrollOffset
(
Offset
pixelDelta
)
{
switch
(
config
.
scrollDirection
)
{
case
Axis
.
horizontal
:
...
...
@@ -211,6 +283,8 @@ abstract class ScrollableState<T extends Scrollable> extends State<T> {
/// Returns a two-dimensional representation of the scroll offset, accounting
/// for the scroll direction and scroll anchor.
///
/// See the definition of [ScrollableState] for more details.
Offset
scrollOffsetToPixelDelta
(
double
scrollOffset
)
{
switch
(
config
.
scrollDirection
)
{
case
Axis
.
horizontal
:
...
...
@@ -220,79 +294,19 @@ abstract class ScrollableState<T extends Scrollable> extends State<T> {
}
}
ScrollBehavior
_scrollBehavior
;
/// Subclasses should override this function to create the [ScrollBehavior]
/// they desire.
ScrollBehavior
createScrollBehavior
();
/// The current scroll behavior of this widget.
///
/// Scroll behaviors control where the boundaries of the scrollable are placed
/// and how the scrolling physics should behave near those boundaries and
/// after the user stops directly manipulating the scrollable.
ScrollBehavior
get
scrollBehavior
{
if
(
_scrollBehavior
==
null
)
_scrollBehavior
=
createScrollBehavior
();
return
_scrollBehavior
;
}
Map
<
Type
,
GestureRecognizerFactory
>
buildGestureDetectors
()
{
if
(
scrollBehavior
.
isScrollable
)
{
switch
(
config
.
scrollDirection
)
{
case
Axis
.
vertical
:
return
<
Type
,
GestureRecognizerFactory
>{
VerticalDragGestureRecognizer:
(
VerticalDragGestureRecognizer
recognizer
)
{
return
(
recognizer
??=
new
VerticalDragGestureRecognizer
())
..
onStart
=
_handleDragStart
..
onUpdate
=
_handleDragUpdate
..
onEnd
=
_handleDragEnd
;
}
};
case
Axis
.
horizontal
:
return
<
Type
,
GestureRecognizerFactory
>{
HorizontalDragGestureRecognizer:
(
HorizontalDragGestureRecognizer
recognizer
)
{
return
(
recognizer
??=
new
HorizontalDragGestureRecognizer
())
..
onStart
=
_handleDragStart
..
onUpdate
=
_handleDragUpdate
..
onEnd
=
_handleDragEnd
;
}
};
}
}
return
const
<
Type
,
GestureRecognizerFactory
>{};
return
_scrollBehavior
??=
createScrollBehavior
();
}
ScrollBehavior
_scrollBehavior
;
final
GlobalKey
_gestureDetectorKey
=
new
GlobalKey
();
void
updateGestureDetector
()
{
_gestureDetectorKey
.
currentState
.
replaceGestureRecognizers
(
buildGestureDetectors
());
}
Widget
build
(
BuildContext
context
)
{
return
new
RawGestureDetector
(
key:
_gestureDetectorKey
,
gestures:
buildGestureDetectors
(),
behavior:
HitTestBehavior
.
opaque
,
child:
new
Listener
(
child:
buildContent
(
context
),
onPointerDown:
_handlePointerDown
)
);
}
/// Subclasses should override this function to build the interior of their
/// scrollable widget. Scrollable wraps the returned widget in a
/// [GestureDetector] to observe the user's interaction with this widget and
/// to adjust the scroll offset accordingly.
Widget
buildContent
(
BuildContext
context
);
Future
_animateTo
(
double
newScrollOffset
,
Duration
duration
,
Curve
curve
)
{
_controller
.
stop
();
_controller
.
value
=
scrollOffset
;
_dispatchOnScrollStartIfNeeded
();
return
_controller
.
animateTo
(
newScrollOffset
,
duration:
duration
,
curve:
curve
).
then
(
_dispatchOnScrollEndIfNeeded
);
}
/// Subclasses should override this function to create the [ScrollBehavior]
/// they desire.
ScrollBehavior
createScrollBehavior
();
bool
_scrollOffsetIsInBounds
(
double
scrollOffset
)
{
if
(
scrollBehavior
is
!
ExtentScrollBehavior
)
...
...
@@ -301,68 +315,6 @@ abstract class ScrollableState<T extends Scrollable> extends State<T> {
return
scrollOffset
>=
behavior
.
minScrollOffset
&&
scrollOffset
<
behavior
.
maxScrollOffset
;
}
Simulation
_createFlingSimulation
(
double
scrollVelocity
)
{
final
Simulation
simulation
=
scrollBehavior
.
createFlingScrollSimulation
(
scrollOffset
,
scrollVelocity
);
if
(
simulation
!=
null
)
{
final
double
endVelocity
=
pixelOffsetToScrollOffset
(
kPixelScrollTolerance
.
velocity
).
abs
()
*
(
scrollVelocity
<
0.0
?
-
1.0
:
1.0
);
final
double
endDistance
=
pixelOffsetToScrollOffset
(
kPixelScrollTolerance
.
distance
).
abs
();
simulation
.
tolerance
=
new
Tolerance
(
velocity:
endVelocity
,
distance:
endDistance
);
}
return
simulation
;
}
/// Returns the snapped offset closest to the given scroll offset.
double
snapScrollOffset
(
double
scrollOffset
)
{
RenderBox
box
=
context
.
findRenderObject
();
return
config
.
snapOffsetCallback
==
null
?
scrollOffset
:
config
.
snapOffsetCallback
(
scrollOffset
,
box
.
size
);
}
/// Whether this scrollable should attempt to snap scroll offsets.
bool
get
shouldSnapScrollOffset
=>
config
.
snapOffsetCallback
!=
null
;
Simulation
_createSnapSimulation
(
double
scrollVelocity
)
{
if
(!
shouldSnapScrollOffset
||
scrollVelocity
==
0.0
||
!
_scrollOffsetIsInBounds
(
scrollOffset
))
return
null
;
Simulation
simulation
=
_createFlingSimulation
(
scrollVelocity
);
if
(
simulation
==
null
)
return
null
;
final
double
endScrollOffset
=
simulation
.
x
(
double
.
INFINITY
);
if
(
endScrollOffset
.
isNaN
)
return
null
;
final
double
snappedScrollOffset
=
snapScrollOffset
(
endScrollOffset
);
// invokes the config.snapOffsetCallback callback
if
(!
_scrollOffsetIsInBounds
(
snappedScrollOffset
))
return
null
;
final
double
snapVelocity
=
scrollVelocity
.
abs
()
*
(
snappedScrollOffset
-
scrollOffset
).
sign
;
final
double
endVelocity
=
pixelOffsetToScrollOffset
(
kPixelScrollTolerance
.
velocity
).
abs
()
*
(
scrollVelocity
<
0.0
?
-
1.0
:
1.0
);
Simulation
toSnapSimulation
=
scrollBehavior
.
createSnapScrollSimulation
(
scrollOffset
,
snappedScrollOffset
,
snapVelocity
,
endVelocity
);
if
(
toSnapSimulation
==
null
)
return
null
;
final
double
scrollOffsetMin
=
math
.
min
(
scrollOffset
,
snappedScrollOffset
);
final
double
scrollOffsetMax
=
math
.
max
(
scrollOffset
,
snappedScrollOffset
);
return
new
ClampedSimulation
(
toSnapSimulation
,
xMin:
scrollOffsetMin
,
xMax:
scrollOffsetMax
);
}
Future
_startToEndAnimation
(
double
scrollVelocity
)
{
_controller
.
stop
();
Simulation
simulation
=
_createSnapSimulation
(
scrollVelocity
)
??
_createFlingSimulation
(
scrollVelocity
);
if
(
simulation
==
null
)
return
new
Future
.
value
();
_dispatchOnScrollStartIfNeeded
();
return
_controller
.
animateWith
(
simulation
).
then
(
_dispatchOnScrollEndIfNeeded
);
}
void
dispose
()
{
_controller
.
stop
();
super
.
dispose
();
}
void
_handleAnimationChanged
()
{
_setScrollOffset
(
_controller
.
value
);
}
...
...
@@ -386,6 +338,15 @@ abstract class ScrollableState<T extends Scrollable> extends State<T> {
dispatchOnScrollEnd
();
}
/// Scroll this widget by the given scroll delta.
///
/// If a non-null [duration] is provided, the widget will animate to the new
/// scroll offset over the given duration with the given curve.
Future
scrollBy
(
double
scrollDelta
,
{
Duration
duration
,
Curve
curve:
Curves
.
ease
})
{
double
newScrollOffset
=
scrollBehavior
.
applyCurve
(
_scrollOffset
,
scrollDelta
);
return
scrollTo
(
newScrollOffset
,
duration:
duration
,
curve:
curve
);
}
/// Scroll this widget to the given scroll offset.
///
/// If a non-null [duration] is provided, the widget will animate to the new
...
...
@@ -408,13 +369,11 @@ abstract class ScrollableState<T extends Scrollable> extends State<T> {
return
_animateTo
(
newScrollOffset
,
duration
,
curve
);
}
/// Scroll this widget by the given scroll delta.
///
/// If a non-null [duration] is provided, the widget will animate to the new
/// scroll offset over the given duration with the given curve.
Future
scrollBy
(
double
scrollDelta
,
{
Duration
duration
,
Curve
curve:
Curves
.
ease
})
{
double
newScrollOffset
=
scrollBehavior
.
applyCurve
(
_scrollOffset
,
scrollDelta
);
return
scrollTo
(
newScrollOffset
,
duration:
duration
,
curve:
curve
);
Future
_animateTo
(
double
newScrollOffset
,
Duration
duration
,
Curve
curve
)
{
_controller
.
stop
();
_controller
.
value
=
scrollOffset
;
_dispatchOnScrollStartIfNeeded
();
return
_controller
.
animateTo
(
newScrollOffset
,
duration:
duration
,
curve:
curve
).
then
(
_dispatchOnScrollEndIfNeeded
);
}
/// Fling the scroll offset with the given velocity.
...
...
@@ -437,18 +396,88 @@ abstract class ScrollableState<T extends Scrollable> extends State<T> {
return
_startToEndAnimation
(
0.0
);
}
Future
_startToEndAnimation
(
double
scrollVelocity
)
{
_controller
.
stop
();
Simulation
simulation
=
_createSnapSimulation
(
scrollVelocity
)
??
_createFlingSimulation
(
scrollVelocity
);
if
(
simulation
==
null
)
return
new
Future
.
value
();
_dispatchOnScrollStartIfNeeded
();
return
_controller
.
animateWith
(
simulation
).
then
(
_dispatchOnScrollEndIfNeeded
);
}
/// Whether this scrollable should attempt to snap scroll offsets.
bool
get
shouldSnapScrollOffset
=>
config
.
snapOffsetCallback
!=
null
;
/// Returns the snapped offset closest to the given scroll offset.
double
snapScrollOffset
(
double
scrollOffset
)
{
RenderBox
box
=
context
.
findRenderObject
();
return
config
.
snapOffsetCallback
==
null
?
scrollOffset
:
config
.
snapOffsetCallback
(
scrollOffset
,
box
.
size
);
}
Simulation
_createSnapSimulation
(
double
scrollVelocity
)
{
if
(!
shouldSnapScrollOffset
||
scrollVelocity
==
0.0
||
!
_scrollOffsetIsInBounds
(
scrollOffset
))
return
null
;
Simulation
simulation
=
_createFlingSimulation
(
scrollVelocity
);
if
(
simulation
==
null
)
return
null
;
final
double
endScrollOffset
=
simulation
.
x
(
double
.
INFINITY
);
if
(
endScrollOffset
.
isNaN
)
return
null
;
final
double
snappedScrollOffset
=
snapScrollOffset
(
endScrollOffset
);
// invokes the config.snapOffsetCallback callback
if
(!
_scrollOffsetIsInBounds
(
snappedScrollOffset
))
return
null
;
final
double
snapVelocity
=
scrollVelocity
.
abs
()
*
(
snappedScrollOffset
-
scrollOffset
).
sign
;
final
double
endVelocity
=
pixelOffsetToScrollOffset
(
kPixelScrollTolerance
.
velocity
).
abs
()
*
(
scrollVelocity
<
0.0
?
-
1.0
:
1.0
);
Simulation
toSnapSimulation
=
scrollBehavior
.
createSnapScrollSimulation
(
scrollOffset
,
snappedScrollOffset
,
snapVelocity
,
endVelocity
);
if
(
toSnapSimulation
==
null
)
return
null
;
final
double
scrollOffsetMin
=
math
.
min
(
scrollOffset
,
snappedScrollOffset
);
final
double
scrollOffsetMax
=
math
.
max
(
scrollOffset
,
snappedScrollOffset
);
return
new
ClampedSimulation
(
toSnapSimulation
,
xMin:
scrollOffsetMin
,
xMax:
scrollOffsetMax
);
}
Simulation
_createFlingSimulation
(
double
scrollVelocity
)
{
final
Simulation
simulation
=
scrollBehavior
.
createFlingScrollSimulation
(
scrollOffset
,
scrollVelocity
);
if
(
simulation
!=
null
)
{
final
double
endVelocity
=
pixelOffsetToScrollOffset
(
kPixelScrollTolerance
.
velocity
).
abs
()
*
(
scrollVelocity
<
0.0
?
-
1.0
:
1.0
);
final
double
endDistance
=
pixelOffsetToScrollOffset
(
kPixelScrollTolerance
.
distance
).
abs
();
simulation
.
tolerance
=
new
Tolerance
(
velocity:
endVelocity
,
distance:
endDistance
);
}
return
simulation
;
}
bool
_isBetweenOnScrollStartAndOnScrollEnd
=
false
;
/// Calls the onScroll callback.
///
/// Subclasses can override this function to hook the scroll callback.
void
dispatchOnScroll
()
{
assert
(
_isBetweenOnScrollStartAndOnScrollEnd
);
if
(
config
.
onScroll
!=
null
)
config
.
onScroll
(
_scrollOffset
);
}
void
_handlePointerDown
(
_
)
{
_controller
.
stop
();
}
void
_handleDragStart
(
_
)
{
_dispatchOnScrollStartIfNeeded
();
}
void
_dispatchOnScrollStartIfNeeded
()
{
if
(!
_isBetweenOnScrollStartAndOnScrollEnd
)
dispatchOnScrollStart
();
}
void
_dispatchOnScrollEndIfNeeded
(
_
)
{
if
(
_isBetweenOnScrollStartAndOnScrollEnd
)
dispatchOnScrollEnd
();
}
/// Calls the onScrollStart callback.
///
/// Subclasses can override this function to hook the scroll start callback.
...
...
@@ -459,13 +488,19 @@ abstract class ScrollableState<T extends Scrollable> extends State<T> {
config
.
onScrollStart
(
_scrollOffset
);
}
/// Calls the onScroll callback.
///
/// Subclasses can override this function to hook the scroll callback.
void
dispatchOnScroll
()
{
assert
(
_isBetweenOnScrollStartAndOnScrollEnd
);
if
(
config
.
onScroll
!=
null
)
config
.
onScroll
(
_scrollOffset
);
void
_handleDragUpdate
(
double
delta
)
{
scrollBy
(
pixelOffsetToScrollOffset
(
delta
));
}
Future
_handleDragEnd
(
Velocity
velocity
)
{
double
scrollVelocity
=
pixelDeltaToScrollOffset
(
velocity
.
pixelsPerSecond
)
/
Duration
.
MILLISECONDS_PER_SECOND
;
// The gesture velocity properties are pixels/second, config min,max limits are pixels/ms
return
fling
(
scrollVelocity
.
clamp
(-
kMaxFlingVelocity
,
kMaxFlingVelocity
)).
then
(
_dispatchOnScrollEndIfNeeded
);
}
void
_dispatchOnScrollEndIfNeeded
(
_
)
{
if
(
_isBetweenOnScrollStartAndOnScrollEnd
)
dispatchOnScrollEnd
();
}
/// Calls the dispatchOnScrollEnd callback.
...
...
@@ -478,23 +513,82 @@ abstract class ScrollableState<T extends Scrollable> extends State<T> {
config
.
onScrollEnd
(
_scrollOffset
);
}
void
_handlePointerDown
(
_
)
{
_controller
.
stop
();
}
final
GlobalKey
_gestureDetectorKey
=
new
GlobalKey
();
void
_handleDragStart
(
_
)
{
_dispatchOnScrollStartIfNeeded
();
Widget
build
(
BuildContext
context
)
{
return
new
RawGestureDetector
(
key:
_gestureDetectorKey
,
gestures:
buildGestureDetectors
(),
behavior:
HitTestBehavior
.
opaque
,
child:
new
Listener
(
child:
buildContent
(
context
),
onPointerDown:
_handlePointerDown
)
);
}
void
_handleDragUpdate
(
double
delta
)
{
scrollBy
(
pixelOffsetToScrollOffset
(
delta
));
/// Fixes up the gesture detector to listen to the appropriate
/// gestures based on the current information about the layout.
///
/// This method should be called from the
/// [onPaintOffsetUpdateNeeded] or [onExtentsChanged] handler given
/// to the [Viewport] or equivalent used by the subclass's
/// [buildContent] method. See the [buildContent] method's
/// description for details.
void
updateGestureDetector
()
{
_gestureDetectorKey
.
currentState
.
replaceGestureRecognizers
(
buildGestureDetectors
());
}
Future
_handleDragEnd
(
Velocity
velocity
)
{
double
scrollVelocity
=
pixelDeltaToScrollOffset
(
velocity
.
pixelsPerSecond
)
/
Duration
.
MILLISECONDS_PER_SECOND
;
// The gesture velocity properties are pixels/second, config min,max limits are pixels/ms
return
fling
(
scrollVelocity
.
clamp
(-
kMaxFlingVelocity
,
kMaxFlingVelocity
)).
then
(
_dispatchOnScrollEndIfNeeded
);
/// Return the gesture detectors, in the form expected by
/// [RawGestureDetector.gestures] and
/// [RawGestureDetectorState.replaceGestureRecognizers], that are
/// applicable to this [Scrollable] in its current state.
///
/// This is called by [build] and [updateGestureDetector].
Map
<
Type
,
GestureRecognizerFactory
>
buildGestureDetectors
()
{
if
(
scrollBehavior
.
isScrollable
)
{
switch
(
config
.
scrollDirection
)
{
case
Axis
.
vertical
:
return
<
Type
,
GestureRecognizerFactory
>{
VerticalDragGestureRecognizer:
(
VerticalDragGestureRecognizer
recognizer
)
{
return
(
recognizer
??=
new
VerticalDragGestureRecognizer
())
..
onStart
=
_handleDragStart
..
onUpdate
=
_handleDragUpdate
..
onEnd
=
_handleDragEnd
;
}
};
case
Axis
.
horizontal
:
return
<
Type
,
GestureRecognizerFactory
>{
HorizontalDragGestureRecognizer:
(
HorizontalDragGestureRecognizer
recognizer
)
{
return
(
recognizer
??=
new
HorizontalDragGestureRecognizer
())
..
onStart
=
_handleDragStart
..
onUpdate
=
_handleDragUpdate
..
onEnd
=
_handleDragEnd
;
}
};
}
}
return
const
<
Type
,
GestureRecognizerFactory
>{};
}
/// Subclasses should override this function to build the interior of their
/// scrollable widget. Scrollable wraps the returned widget in a
/// [GestureDetector] to observe the user's interaction with this widget and
/// to adjust the scroll offset accordingly.
///
/// The widgets used by this method should be widgets that provide a
/// layout-time callback that reports the sizes that are relevant to
/// the scroll offset (typically the size of the scrollable
/// container and the scrolled contents). [Viewport] and
/// [MixedViewport] provide an [onPaintOffsetUpdateNeeded] callback
/// for this purpose; [GridViewport], [ListViewport], and
/// [LazyListViewport] provide an [onExtentsChanged] callback for
/// this purpose.
///
/// This callback should be used to update the scroll behavior, if
/// necessary, and then to call [updateGestureDetector] to update
/// the gesture detectors accordingly.
Widget
buildContent
(
BuildContext
context
);
}
/// Indicates that a descendant scrollable has scrolled.
...
...
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