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
dac80aac
Commit
dac80aac
authored
Mar 21, 2017
by
Hans Muller
Committed by
GitHub
Mar 21, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Make min/max fling velocity and min fling distance ScrollPhysics properties (#8928)
parent
14933de9
Changes
6
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
284 additions
and
209 deletions
+284
-209
drag.dart
packages/flutter/lib/src/gestures/drag.dart
+62
-27
velocity_tracker.dart
packages/flutter/lib/src/gestures/velocity_tracker.dart
+158
-159
scroll_physics.dart
packages/flutter/lib/src/widgets/scroll_physics.dart
+22
-15
scroll_position.dart
packages/flutter/lib/src/widgets/scroll_position.dart
+27
-0
scrollable.dart
packages/flutter/lib/src/widgets/scrollable.dart
+14
-7
modal_bottom_sheet_test.dart
packages/flutter/test/material/modal_bottom_sheet_test.dart
+1
-1
No files found.
packages/flutter/lib/src/gestures/drag.dart
View file @
dac80aac
...
...
@@ -204,12 +204,6 @@ typedef void GestureDragEndCallback(DragEndDetails details);
/// See [DragGestureRecognizer.onCancel].
typedef
void
GestureDragCancelCallback
(
);
bool
_isFlingGesture
(
Velocity
velocity
)
{
assert
(
velocity
!=
null
);
final
double
speedSquared
=
velocity
.
pixelsPerSecond
.
distanceSquared
;
return
speedSquared
>
kMinFlingVelocity
*
kMinFlingVelocity
;
}
/// Recognizes movement.
///
/// In contrast to [MultiDragGestureRecognizer], [DragGestureRecognizer]
...
...
@@ -256,10 +250,30 @@ abstract class DragGestureRecognizer extends OneSequenceGestureRecognizer {
/// The pointer that previously triggered [onDown] did not complete.
GestureDragCancelCallback
onCancel
;
/// The minimum distance an input pointer drag must have moved to
/// to be considered a fling gesture.
///
/// This value is typically compared with the distance traveled along the
/// scrolling axis. If null then [kTouchSlop] is used.
double
minFlingDistance
;
/// The minimum velocity for an input pointer drag to be considered fling.
///
/// This value is typically compared with the magnitude of fling gesture's
/// velocity along the scrolling axis. If null then [kMinFlingVelocity]
/// is used.
double
minFlingVelocity
;
/// Fling velocity magnitudes will be clamped to this value.
///
/// If null then [kMaxFlingVelocity] is used.
double
maxFlingVelocity
;
_DragState
_state
=
_DragState
.
ready
;
Point
_initialPosition
;
Offset
_pendingDragOffset
;
bool
_isFlingGesture
(
VelocityEstimate
estimate
);
Offset
_getDeltaForDetails
(
Offset
delta
);
double
_getPrimaryValueFromOffset
(
Offset
value
);
bool
get
_hasSufficientPendingDragDeltaToAccept
;
...
...
@@ -345,11 +359,10 @@ abstract class DragGestureRecognizer extends OneSequenceGestureRecognizer {
final
VelocityTracker
tracker
=
_velocityTrackers
[
pointer
];
assert
(
tracker
!=
null
);
Velocity
velocity
=
tracker
.
getVelocity
();
if
(
velocity
!=
null
&&
_isFlingGesture
(
velocity
))
{
final
Offset
pixelsPerSecond
=
velocity
.
pixelsPerSecond
;
if
(
pixelsPerSecond
.
distanceSquared
>
kMaxFlingVelocity
*
kMaxFlingVelocity
)
velocity
=
new
Velocity
(
pixelsPerSecond:
(
pixelsPerSecond
/
pixelsPerSecond
.
distance
)
*
kMaxFlingVelocity
);
final
VelocityEstimate
estimate
=
tracker
.
getVelocityEstimate
();
if
(
estimate
!=
null
&&
_isFlingGesture
(
estimate
))
{
final
Velocity
velocity
=
new
Velocity
(
pixelsPerSecond:
estimate
.
pixelsPerSecond
)
.
clampMagnitude
(
minFlingVelocity
??
kMinFlingVelocity
,
maxFlingVelocity
??
kMaxFlingVelocity
);
invokeCallback
<
Null
>(
'onEnd'
,
()
=>
onEnd
(
new
DragEndDetails
(
// ignore: STRONG_MODE_INVALID_CAST_FUNCTION_EXPR, https://github.com/dart-lang/sdk/issues/27504
velocity:
velocity
,
primaryVelocity:
_getPrimaryValueFromOffset
(
velocity
.
pixelsPerSecond
),
...
...
@@ -379,6 +392,13 @@ abstract class DragGestureRecognizer extends OneSequenceGestureRecognizer {
///
/// * [VerticalMultiDragGestureRecognizer]
class
VerticalDragGestureRecognizer
extends
DragGestureRecognizer
{
@override
bool
_isFlingGesture
(
VelocityEstimate
estimate
)
{
final
double
minVelocity
=
minFlingVelocity
??
kMinFlingVelocity
;
final
double
minDistance
=
minFlingDistance
??
kTouchSlop
;
return
estimate
.
pixelsPerSecond
.
dy
.
abs
()
>
minVelocity
&&
estimate
.
offset
.
dy
.
abs
()
>
minDistance
;
}
@override
bool
get
_hasSufficientPendingDragDeltaToAccept
=>
_pendingDragOffset
.
dy
.
abs
()
>
kTouchSlop
;
...
...
@@ -400,6 +420,13 @@ class VerticalDragGestureRecognizer extends DragGestureRecognizer {
///
/// * [HorizontalMultiDragGestureRecognizer]
class
HorizontalDragGestureRecognizer
extends
DragGestureRecognizer
{
@override
bool
_isFlingGesture
(
VelocityEstimate
estimate
)
{
final
double
minVelocity
=
minFlingVelocity
??
kMinFlingVelocity
;
final
double
minDistance
=
minFlingDistance
??
kTouchSlop
;
return
estimate
.
pixelsPerSecond
.
dx
.
abs
()
>
minVelocity
&&
estimate
.
offset
.
dx
.
abs
()
>
minDistance
;
}
@override
bool
get
_hasSufficientPendingDragDeltaToAccept
=>
_pendingDragOffset
.
dx
.
abs
()
>
kTouchSlop
;
...
...
@@ -420,6 +447,14 @@ class HorizontalDragGestureRecognizer extends DragGestureRecognizer {
/// * [ImmediateMultiDragGestureRecognizer]
/// * [DelayedMultiDragGestureRecognizer]
class
PanGestureRecognizer
extends
DragGestureRecognizer
{
@override
bool
_isFlingGesture
(
VelocityEstimate
estimate
)
{
final
double
minVelocity
=
minFlingVelocity
??
kMinFlingVelocity
;
final
double
minDistance
=
minFlingDistance
??
kTouchSlop
;
return
estimate
.
pixelsPerSecond
.
distanceSquared
>
minVelocity
*
minVelocity
&&
estimate
.
offset
.
distanceSquared
>
minDistance
*
minDistance
;
}
@override
bool
get
_hasSufficientPendingDragDeltaToAccept
{
return
_pendingDragOffset
.
distance
>
kPanSlop
;
...
...
packages/flutter/lib/src/gestures/velocity_tracker.dart
View file @
dac80aac
...
...
@@ -8,135 +8,6 @@ import 'lsq_solver.dart';
export
'dart:ui'
show
Point
,
Offset
;
class
_Estimate
{
const
_Estimate
({
this
.
xCoefficients
,
this
.
yCoefficients
,
this
.
time
,
this
.
degree
,
this
.
confidence
});
final
List
<
double
>
xCoefficients
;
final
List
<
double
>
yCoefficients
;
final
Duration
time
;
final
int
degree
;
final
double
confidence
;
}
abstract
class
_VelocityTrackerStrategy
{
void
addMovement
(
Duration
timeStamp
,
Point
position
);
_Estimate
getEstimate
();
void
clear
();
}
class
_Movement
{
const
_Movement
(
this
.
eventTime
,
this
.
position
);
final
Duration
eventTime
;
final
Point
position
;
@override
String
toString
()
=>
'Movement(
$position
at
$eventTime
)'
;
}
// TODO: On iOS we're not necccessarily seeing all of the motion events. See:
// https://github.com/flutter/flutter/issues/4737#issuecomment-241076994
class
_LeastSquaresVelocityTrackerStrategy
extends
_VelocityTrackerStrategy
{
_LeastSquaresVelocityTrackerStrategy
(
this
.
degree
);
final
int
degree
;
final
List
<
_Movement
>
_movements
=
new
List
<
_Movement
>(
kHistorySize
);
int
_index
=
0
;
static
const
int
kHistorySize
=
20
;
static
const
int
kHorizonMilliseconds
=
100
;
// The maximum length of time between two move events to allow before
// assuming the pointer stopped.
static
const
int
kAssumePointerMoveStoppedMilliseconds
=
40
;
@override
void
addMovement
(
Duration
timeStamp
,
Point
position
)
{
_index
+=
1
;
if
(
_index
==
kHistorySize
)
_index
=
0
;
_movements
[
_index
]
=
new
_Movement
(
timeStamp
,
position
);
}
@override
_Estimate
getEstimate
()
{
// Iterate over movement samples in reverse time order and collect samples.
final
List
<
double
>
x
=
<
double
>[];
final
List
<
double
>
y
=
<
double
>[];
final
List
<
double
>
w
=
<
double
>[];
final
List
<
double
>
time
=
<
double
>[];
int
m
=
0
;
int
index
=
_index
;
final
_Movement
newestMovement
=
_movements
[
index
];
_Movement
previousMovement
=
newestMovement
;
if
(
newestMovement
==
null
)
return
null
;
do
{
final
_Movement
movement
=
_movements
[
index
];
if
(
movement
==
null
)
break
;
final
double
age
=
(
newestMovement
.
eventTime
-
movement
.
eventTime
).
inMilliseconds
.
toDouble
();
final
double
delta
=
(
movement
.
eventTime
-
previousMovement
.
eventTime
).
inMilliseconds
.
abs
().
toDouble
();
previousMovement
=
movement
;
if
(
age
>
kHorizonMilliseconds
||
delta
>
kAssumePointerMoveStoppedMilliseconds
)
break
;
final
Point
position
=
movement
.
position
;
x
.
add
(
position
.
x
);
y
.
add
(
position
.
y
);
w
.
add
(
1.0
);
time
.
add
(-
age
);
index
=
(
index
==
0
?
kHistorySize
:
index
)
-
1
;
m
+=
1
;
}
while
(
m
<
kHistorySize
);
// Calculate a least squares polynomial fit.
int
n
=
degree
;
if
(
n
>
m
-
1
)
n
=
m
-
1
;
if
(
n
>=
1
)
{
final
LeastSquaresSolver
xSolver
=
new
LeastSquaresSolver
(
time
,
x
,
w
);
final
PolynomialFit
xFit
=
xSolver
.
solve
(
n
);
if
(
xFit
!=
null
)
{
final
LeastSquaresSolver
ySolver
=
new
LeastSquaresSolver
(
time
,
y
,
w
);
final
PolynomialFit
yFit
=
ySolver
.
solve
(
n
);
if
(
yFit
!=
null
)
{
return
new
_Estimate
(
xCoefficients:
xFit
.
coefficients
,
yCoefficients:
yFit
.
coefficients
,
time:
newestMovement
.
eventTime
,
degree:
n
,
confidence:
xFit
.
confidence
*
yFit
.
confidence
);
}
}
}
// No velocity data available for this pointer, but we do have its current
// position.
return
new
_Estimate
(
xCoefficients:
<
double
>[
x
[
0
]
],
yCoefficients:
<
double
>[
y
[
0
]
],
time:
newestMovement
.
eventTime
,
degree:
0
,
confidence:
1.0
);
}
@override
void
clear
()
{
_index
=
-
1
;
}
}
/// A velocity in two dimensions.
class
Velocity
{
/// Creates a velocity.
...
...
@@ -165,6 +36,27 @@ class Velocity {
pixelsPerSecond:
pixelsPerSecond
+
other
.
pixelsPerSecond
);
}
/// Return a velocity whose magnitude has been clamped to [minValue]
/// and [maxValue].
///
/// If the magnitude of this Velocity is less than minValue then return a new
/// Velocity with the same direction and with magnitude [minValue]. Similarly,
/// if the magnitude of this Velocity is greater than maxValue then return a
/// new Velocity with the same direction and magnitude [maxValue].
///
/// If the magnitude of this Velocity is within the specified bounds then
/// just return this.
Velocity
clampMagnitude
(
double
minValue
,
double
maxValue
)
{
assert
(
minValue
!=
null
&&
minValue
>=
0.0
);
assert
(
maxValue
!=
null
&&
maxValue
>=
0.0
&&
maxValue
>=
minValue
);
final
double
valueSquared
=
pixelsPerSecond
.
distanceSquared
;
if
(
valueSquared
>
maxValue
*
maxValue
)
return
new
Velocity
(
pixelsPerSecond:
(
pixelsPerSecond
/
pixelsPerSecond
.
distance
)
*
maxValue
);
if
(
valueSquared
<
minValue
*
minValue
)
return
new
Velocity
(
pixelsPerSecond:
(
pixelsPerSecond
/
pixelsPerSecond
.
distance
)
*
minValue
);
return
this
;
}
@override
bool
operator
==(
dynamic
other
)
{
if
(
other
is
!
Velocity
)
...
...
@@ -180,39 +72,152 @@ class Velocity {
String
toString
()
=>
'Velocity(
${pixelsPerSecond.dx.toStringAsFixed(1)}
,
${pixelsPerSecond.dy.toStringAsFixed(1)}
)'
;
}
/// Computes a pointer velocity based on data from PointerMove events.
/// A two dimensional velocity estimate.
///
/// VelocityEstimates are computed by [VelocityTracker.getVelocityEstimate]. An
/// estimate's [confidence] measures how well the the velocity tracker's position
/// data fit a straight line, [duration] is the time that elapsed between the
/// first and last position sample used to compute the velocity, and [offset]
/// is similarly the difference between the first and last positions.
///
/// See also:
///
/// * VelocityTracker, which computes [VelocityEstimate]s.
/// * Velocity, which encapsulates (just) a velocity vector and provides some
/// useful velocity operations.
class
VelocityEstimate
{
/// Creates a dimensional velocity estimate.
const
VelocityEstimate
({
this
.
pixelsPerSecond
,
this
.
confidence
,
this
.
duration
,
this
.
offset
,
});
/// The number of pixels per second of velocity in the x and y directions.
final
Offset
pixelsPerSecond
;
/// A value between 0.0 and 1.0 that indicates how well [VelocityTracker]
/// was able to fit a straight line to its position data.
///
/// The value of this property is 1.0 for a perfect fit, 0.0 for a poor fit.
final
double
confidence
;
/// The time that elapsed between the first and last position sample used
/// to compute [pixelsPerSecond].
final
Duration
duration
;
/// The difference between the first and last position sample used
/// to compute [pixelsPerSecond].
final
Offset
offset
;
@override
String
toString
()
=>
'VelocityEstimate(
${pixelsPerSecond.dx.toStringAsFixed(1)}
,
${pixelsPerSecond.dy.toStringAsFixed(1)}
)'
;
}
class
_PointAtTime
{
const
_PointAtTime
(
this
.
point
,
this
.
time
);
final
Duration
time
;
final
Point
point
;
@override
String
toString
()
=>
'_PointAtTime(
$point
at
$time
)'
;
}
/// Computes a pointer's velocity based on data from PointerMove events.
///
/// The input data is provided by calling addPosition(). Adding data
/// is cheap.
///
/// To obtain a velocity, call getVelocity(). This will compute the
/// velocity based on the data added so far. Only call this when you
/// need to use the velocity, as it is comparatively expensive.
/// To obtain a velocity, call [getVelocity] or [getVelocityEstimate].
/// This will compute the velocity based on the data added so far. Only
/// call this when you need to use the velocity, as it is comparatively
/// expensive.
///
/// The quality of the velocity estimation will be better if more data
/// points have been received.
class
VelocityTracker
{
/// Creates a velocity tracker.
VelocityTracker
()
:
_strategy
=
_createStrategy
();
// VelocityTracker is designed to easily be adapted to using different
// algorithms in the future, potentially picking algorithms on the fly based
// on hardware or other environment factors.
//
// For now, though, we just use the _LeastSquaresVelocityTrackerStrategy
// defined above.
static
const
int
_kAssumePointerMoveStoppedMilliseconds
=
40
;
static
const
int
_kHistorySize
=
20
;
static
const
int
_kHorizonMilliseconds
=
100
;
static
const
int
_kMinSampleSize
=
3
;
// TODO(ianh): Simplify this. We don't see to need multiple stategies.
// Circular buffer; current sample at _index.
final
List
<
_PointAtTime
>
_samples
=
new
List
<
_PointAtTime
>(
_kHistorySize
);
int
_index
=
0
;
static
_VelocityTrackerStrategy
_createStrategy
()
{
return
new
_LeastSquaresVelocityTrackerStrategy
(
2
);
void
addPosition
(
Duration
time
,
Point
position
)
{
_index
+=
1
;
if
(
_index
==
_kHistorySize
)
_index
=
0
;
_samples
[
_index
]
=
new
_PointAtTime
(
position
,
time
);
}
_VelocityTrackerStrategy
_strategy
;
VelocityEstimate
getVelocityEstimate
()
{
final
List
<
double
>
x
=
<
double
>[];
final
List
<
double
>
y
=
<
double
>[];
final
List
<
double
>
w
=
<
double
>[];
final
List
<
double
>
time
=
<
double
>[];
int
sampleCount
=
0
;
int
index
=
_index
;
final
_PointAtTime
newestSample
=
_samples
[
index
];
if
(
newestSample
==
null
)
return
null
;
_PointAtTime
previousSample
=
newestSample
;
_PointAtTime
oldestSample
=
newestSample
;
// Starting with the most recent PointAtTime sample, iterate backwards while
// the samples represent continuous motion.
do
{
final
_PointAtTime
sample
=
_samples
[
index
];
if
(
sample
==
null
)
break
;
final
double
age
=
(
newestSample
.
time
-
sample
.
time
).
inMilliseconds
.
toDouble
();
final
double
delta
=
(
sample
.
time
-
previousSample
.
time
).
inMilliseconds
.
abs
().
toDouble
();
previousSample
=
sample
;
if
(
age
>
_kHorizonMilliseconds
||
delta
>
_kAssumePointerMoveStoppedMilliseconds
)
break
;
oldestSample
=
sample
;
final
Point
position
=
sample
.
point
;
x
.
add
(
position
.
x
);
y
.
add
(
position
.
y
);
w
.
add
(
1.0
);
time
.
add
(-
age
);
index
=
(
index
==
0
?
_kHistorySize
:
index
)
-
1
;
sampleCount
+=
1
;
}
while
(
sampleCount
<
_kHistorySize
);
/// Add a given position corresponding to a specific time.
void
addPosition
(
Duration
timeStamp
,
Point
position
)
{
_strategy
.
addMovement
(
timeStamp
,
position
);
if
(
sampleCount
>=
_kMinSampleSize
)
{
final
LeastSquaresSolver
xSolver
=
new
LeastSquaresSolver
(
time
,
x
,
w
);
final
PolynomialFit
xFit
=
xSolver
.
solve
(
2
);
if
(
xFit
!=
null
)
{
final
LeastSquaresSolver
ySolver
=
new
LeastSquaresSolver
(
time
,
y
,
w
);
final
PolynomialFit
yFit
=
ySolver
.
solve
(
2
);
if
(
yFit
!=
null
)
{
return
new
VelocityEstimate
(
// convert from pixels/ms to pixels/s
pixelsPerSecond:
new
Offset
(
xFit
.
coefficients
[
1
]
*
1000
,
yFit
.
coefficients
[
1
]
*
1000
),
confidence:
xFit
.
confidence
*
yFit
.
confidence
,
duration:
newestSample
.
time
-
oldestSample
.
time
,
offset:
newestSample
.
point
-
oldestSample
.
point
,
);
}
}
}
// We're unable to make a velocity estimate but we did have at least one
// valid pointer position.
return
new
VelocityEstimate
(
pixelsPerSecond:
Offset
.
zero
,
confidence:
1.0
,
duration:
newestSample
.
time
-
oldestSample
.
time
,
offset:
newestSample
.
point
-
oldestSample
.
point
,
);
}
/// Computes the velocity of the pointer at the time of the last
...
...
@@ -223,15 +228,9 @@ class VelocityTracker {
/// getVelocity() will return null if no estimate is available or if
/// the velocity is zero.
Velocity
getVelocity
()
{
final
_Estimate
estimate
=
_strategy
.
getEstimate
();
if
(
estimate
!=
null
&&
estimate
.
degree
>=
1
)
{
return
new
Velocity
(
pixelsPerSecond:
new
Offset
(
// convert from pixels/ms to pixels/s
estimate
.
xCoefficients
[
1
]
*
1000
,
estimate
.
yCoefficients
[
1
]
*
1000
)
);
}
final
VelocityEstimate
estimate
=
getVelocityEstimate
();
if
(
estimate
==
null
||
estimate
.
pixelsPerSecond
==
Offset
.
zero
)
return
null
;
return
new
Velocity
(
pixelsPerSecond:
estimate
.
pixelsPerSecond
);
}
}
packages/flutter/lib/src/widgets/scroll_physics.dart
View file @
dac80aac
...
...
@@ -4,6 +4,7 @@
import
'dart:math'
as
math
;
import
'package:flutter/gestures.dart'
show
kMinFlingVelocity
;
import
'package:flutter/physics.dart'
;
import
'overscroll_indicator.dart'
;
...
...
@@ -81,6 +82,12 @@ class BouncingScrollPhysics extends ScrollPhysics {
}
return
null
;
}
// The ballistic simulation here decelerates more slowly than the one for
// ClampingScrollPhysics so we require a more deliberate input gesture
// to trigger a fling.
@override
double
get
minFlingVelocity
=>
kMinFlingVelocity
*
2.0
;
}
/// Scroll physics for environments that prevent the scroll offset from reaching
...
...
packages/flutter/lib/src/widgets/scroll_position.dart
View file @
dac80aac
...
...
@@ -106,6 +106,33 @@ abstract class ScrollPhysics {
Tolerance
get
tolerance
=>
parent
?.
tolerance
??
_kDefaultTolerance
;
/// The minimum distance an input pointer drag must have moved to
/// to be considered a scroll fling gesture.
///
/// This value is typically compared with the distance traveled along the
/// scrolling axis.
///
/// See also:
///
/// * [VelocityTracker.getVelocityEstimate], which computes the velocity
/// of a press-drag-release gesture.
double
get
minFlingDistance
=>
parent
?.
minFlingDistance
??
kTouchSlop
;
/// The minimum velocity for an input pointer drag to be considered a
/// scroll fling.
///
/// This value is typically compared with the magnitude of fling gesture's
/// velocity along the scrolling axis.
///
/// See also:
///
/// * [VelocityTracker.getVelocityEstimate], which computes the velocity
/// of a press-drag-release gesture.
double
get
minFlingVelocity
=>
parent
?.
minFlingVelocity
??
kMinFlingVelocity
;
/// Scroll fling velocity magnitudes will be clamped to this value.
double
get
maxFlingVelocity
=>
parent
?.
maxFlingVelocity
??
kMaxFlingVelocity
;
@override
String
toString
()
{
if
(
parent
==
null
)
...
...
packages/flutter/lib/src/widgets/scrollable.dart
View file @
dac80aac
...
...
@@ -118,13 +118,14 @@ class ScrollableState extends State<Scrollable> with TickerProviderStateMixin
ScrollPosition
_position
;
ScrollBehavior
_configuration
;
ScrollPhysics
_physics
;
//
only call this from places that will definitely trigger a rebuild
//
Only call this from places that will definitely trigger a rebuild.
void
_updatePosition
()
{
_configuration
=
ScrollConfiguration
.
of
(
context
);
ScrollPhysics
physics
=
_configuration
.
getScrollPhysics
(
context
);
_
physics
=
_configuration
.
getScrollPhysics
(
context
);
if
(
config
.
physics
!=
null
)
physics
=
config
.
physics
.
applyTo
(
physics
);
_physics
=
config
.
physics
.
applyTo
(
_
physics
);
final
ScrollController
controller
=
config
.
controller
;
final
ScrollPosition
oldPosition
=
position
;
if
(
oldPosition
!=
null
)
{
...
...
@@ -135,8 +136,8 @@ class ScrollableState extends State<Scrollable> with TickerProviderStateMixin
scheduleMicrotask
(
oldPosition
.
dispose
);
}
_position
=
controller
?.
createScrollPosition
(
physics
,
this
,
oldPosition
)
??
ScrollController
.
createDefaultScrollPosition
(
physics
,
this
,
oldPosition
);
_position
=
controller
?.
createScrollPosition
(
_
physics
,
this
,
oldPosition
)
??
ScrollController
.
createDefaultScrollPosition
(
_
physics
,
this
,
oldPosition
);
assert
(
position
!=
null
);
controller
?.
attach
(
position
);
}
...
...
@@ -201,7 +202,10 @@ class ScrollableState extends State<Scrollable> with TickerProviderStateMixin
..
onDown
=
_handleDragDown
..
onStart
=
_handleDragStart
..
onUpdate
=
_handleDragUpdate
..
onEnd
=
_handleDragEnd
;
..
onEnd
=
_handleDragEnd
..
minFlingDistance
=
_physics
?.
minFlingDistance
..
minFlingVelocity
=
_physics
?.
minFlingVelocity
..
maxFlingVelocity
=
_physics
?.
maxFlingVelocity
;
}
};
break
;
...
...
@@ -212,7 +216,10 @@ class ScrollableState extends State<Scrollable> with TickerProviderStateMixin
..
onDown
=
_handleDragDown
..
onStart
=
_handleDragStart
..
onUpdate
=
_handleDragUpdate
..
onEnd
=
_handleDragEnd
;
..
onEnd
=
_handleDragEnd
..
minFlingDistance
=
_physics
?.
minFlingDistance
..
minFlingVelocity
=
_physics
?.
minFlingVelocity
..
maxFlingVelocity
=
_physics
?.
maxFlingVelocity
;
}
};
break
;
...
...
packages/flutter/test/material/modal_bottom_sheet_test.dart
View file @
dac80aac
...
...
@@ -102,7 +102,7 @@ void main() {
expect
(
showBottomSheetThenCalled
,
isFalse
);
expect
(
find
.
text
(
'BottomSheet'
),
findsOneWidget
);
await
tester
.
fling
(
find
.
text
(
'BottomSheet'
),
const
Offset
(
0.0
,
2
0.0
),
1000.0
);
await
tester
.
fling
(
find
.
text
(
'BottomSheet'
),
const
Offset
(
0.0
,
3
0.0
),
1000.0
);
await
tester
.
pump
();
// drain the microtask queue (Future completion callback)
expect
(
showBottomSheetThenCalled
,
isTrue
);
...
...
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