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
b2af3260
Unverified
Commit
b2af3260
authored
Feb 15, 2018
by
Ian Hickson
Committed by
GitHub
Feb 15, 2018
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix boundaries in applyClampedDragUpdate (#14444)
parent
53b348a5
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
107 additions
and
2 deletions
+107
-2
nested_scroll_view.dart
packages/flutter/lib/src/widgets/nested_scroll_view.dart
+27
-2
nested_scroll_view_test.dart
packages/flutter/test/widgets/nested_scroll_view_test.dart
+80
-0
No files found.
packages/flutter/lib/src/widgets/nested_scroll_view.dart
View file @
b2af3260
...
...
@@ -895,6 +895,10 @@ class _NestedScrollController extends ScrollController {
}
}
// The _NestedScrollPosition is used by both the inner and outer viewports of a
// NestedScrollView. It tracks the offset to use for those viewports, and knows
// about the _NestedScrollCoordinator, so that when activities are triggered on
// this class, they can defer, or be influenced by, the coordinator.
class
_NestedScrollPosition
extends
ScrollPosition
implements
ScrollActivityDelegate
{
_NestedScrollPosition
({
@required
ScrollPhysics
physics
,
...
...
@@ -945,10 +949,31 @@ class _NestedScrollPosition extends ScrollPosition implements ScrollActivityDele
}
// Returns the amount of delta that was not used.
//
// Positive delta means going down (exposing stuff above), negative delta
// going up (exposing stuff below).
double
applyClampedDragUpdate
(
double
delta
)
{
assert
(
delta
!=
0.0
);
final
double
min
=
delta
<
0.0
?
-
double
.
INFINITY
:
minScrollExtent
;
final
double
max
=
delta
>
0.0
?
double
.
INFINITY
:
maxScrollExtent
;
// If we are going towards the maxScrollExtent (negative scroll offset),
// then the furthest we can be in the minScrollExtent direction is negative
// infinity. For example, if we are already overscrolled, then scrolling to
// reduce the overscroll should not disallow the overscroll.
//
// If we are going towards the minScrollExtent (positive scroll offset),
// then the furthest we can be in the minScrollExtent direction is wherever
// we are now, if we are already overscrolled (in which case pixels is less
// than the minScrollExtent), or the minScrollExtent if we are not.
//
// In other words, we cannot, via applyClampedDragUpdate, _enter_ an
// overscroll situation.
//
// An overscroll situation might be nonetheless entered via several means.
// One is if the physics allow it, via applyFullDragUpdate (see below). An
// overscroll situation can also be forced, e.g. if the scroll position is
// artificially set using the scroll controller.
final
double
min
=
delta
<
0.0
?
-
double
.
INFINITY
:
math
.
min
(
minScrollExtent
,
pixels
);
// The logic for max is equivalent but on the other side.
final
double
max
=
delta
>
0.0
?
double
.
INFINITY
:
math
.
max
(
maxScrollExtent
,
pixels
);
final
double
oldPixels
=
pixels
;
final
double
newPixels
=
(
pixels
-
delta
).
clamp
(
min
,
max
);
final
double
clampedDelta
=
newPixels
-
pixels
;
...
...
packages/flutter/test/widgets/nested_scroll_view_test.dart
View file @
b2af3260
...
...
@@ -566,4 +566,84 @@ void main() {
expect
(
buildCount
,
expectedBuildCount
);
expect
(
find
.
byType
(
NestedScrollView
),
isNot
(
paints
..
shadow
()));
});
testWidgets
(
'NestedScrollView and iOS bouncing'
,
(
WidgetTester
tester
)
async
{
// This verifies that overscroll bouncing works correctly on iOS. For
// example, this checks that if you pull to overscroll, friction is applied;
// it also makes sure that if you scroll back the other way, the scroll
// positions of the inner and outer list don't have a discontinuity.
debugDefaultTargetPlatformOverride
=
TargetPlatform
.
iOS
;
const
Key
key1
=
const
ValueKey
<
int
>(
1
);
const
Key
key2
=
const
ValueKey
<
int
>(
2
);
await
tester
.
pumpWidget
(
new
MaterialApp
(
home:
new
Material
(
child:
new
DefaultTabController
(
length:
1
,
child:
new
NestedScrollView
(
headerSliverBuilder:
(
BuildContext
context
,
bool
innerBoxIsScrolled
)
{
return
<
Widget
>[
const
SliverPersistentHeader
(
delegate:
const
TestHeader
(
key:
key1
),
),
];
},
body:
new
SingleChildScrollView
(
child:
new
Container
(
height:
1000.0
,
child:
const
Placeholder
(
key:
key2
),
),
),
),
),
),
),
);
expect
(
tester
.
getRect
(
find
.
byKey
(
key1
)),
new
Rect
.
fromLTWH
(
0.0
,
0.0
,
800.0
,
100.0
));
expect
(
tester
.
getRect
(
find
.
byKey
(
key2
)),
new
Rect
.
fromLTWH
(
0.0
,
100.0
,
800.0
,
1000.0
));
final
TestGesture
gesture
=
await
tester
.
startGesture
(
const
Offset
(
10.0
,
10.0
));
await
gesture
.
moveBy
(
const
Offset
(
0.0
,
-
10.0
));
// scroll up
await
tester
.
pump
();
expect
(
tester
.
getRect
(
find
.
byKey
(
key1
)),
new
Rect
.
fromLTWH
(
0.0
,
-
10.0
,
800.0
,
100.0
));
expect
(
tester
.
getRect
(
find
.
byKey
(
key2
)),
new
Rect
.
fromLTWH
(
0.0
,
90.0
,
800.0
,
1000.0
));
await
gesture
.
moveBy
(
const
Offset
(
0.0
,
10.0
));
// scroll back to origin
await
tester
.
pump
();
expect
(
tester
.
getRect
(
find
.
byKey
(
key1
)),
new
Rect
.
fromLTWH
(
0.0
,
0.0
,
800.0
,
100.0
));
expect
(
tester
.
getRect
(
find
.
byKey
(
key2
)),
new
Rect
.
fromLTWH
(
0.0
,
100.0
,
800.0
,
1000.0
));
await
gesture
.
moveBy
(
const
Offset
(
0.0
,
10.0
));
// overscroll
await
gesture
.
moveBy
(
const
Offset
(
0.0
,
10.0
));
// overscroll
await
gesture
.
moveBy
(
const
Offset
(
0.0
,
10.0
));
// overscroll
await
tester
.
pump
();
expect
(
tester
.
getRect
(
find
.
byKey
(
key1
)),
new
Rect
.
fromLTWH
(
0.0
,
0.0
,
800.0
,
100.0
));
expect
(
tester
.
getRect
(
find
.
byKey
(
key2
)).
top
,
greaterThan
(
100.0
));
expect
(
tester
.
getRect
(
find
.
byKey
(
key2
)).
top
,
lessThan
(
130.0
));
await
gesture
.
moveBy
(
const
Offset
(
0.0
,
-
1.0
));
// scroll back a little
await
tester
.
pump
();
expect
(
tester
.
getRect
(
find
.
byKey
(
key1
)),
new
Rect
.
fromLTWH
(
0.0
,
-
1.0
,
800.0
,
100.0
));
expect
(
tester
.
getRect
(
find
.
byKey
(
key2
)).
top
,
greaterThan
(
100.0
));
expect
(
tester
.
getRect
(
find
.
byKey
(
key2
)).
top
,
lessThan
(
129.0
));
await
gesture
.
moveBy
(
const
Offset
(
0.0
,
-
10.0
));
// scroll back a lot
await
tester
.
pump
();
expect
(
tester
.
getRect
(
find
.
byKey
(
key1
)),
new
Rect
.
fromLTWH
(
0.0
,
-
11.0
,
800.0
,
100.0
));
await
gesture
.
moveBy
(
const
Offset
(
0.0
,
20.0
));
// overscroll again
await
tester
.
pump
();
expect
(
tester
.
getRect
(
find
.
byKey
(
key1
)),
new
Rect
.
fromLTWH
(
0.0
,
0.0
,
800.0
,
100.0
));
await
gesture
.
up
();
debugDefaultTargetPlatformOverride
=
null
;
});
}
class
TestHeader
extends
SliverPersistentHeaderDelegate
{
const
TestHeader
({
this
.
key
});
final
Key
key
;
@override
double
get
minExtent
=>
100.0
;
@override
double
get
maxExtent
=>
100.0
;
@override
Widget
build
(
BuildContext
context
,
double
shrinkOffset
,
bool
overlapsContent
)
{
return
new
Placeholder
(
key:
key
);
}
@override
bool
shouldRebuild
(
TestHeader
oldDelegate
)
=>
false
;
}
\ No newline at end of file
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