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
3f812722
Unverified
Commit
3f812722
authored
Nov 11, 2021
by
nt4f04uNd
Committed by
GitHub
Nov 11, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
RangeMaintainingScrollPhysics remove overscroll maintaining when grow (#90608)
parent
6184888e
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
112 additions
and
12 deletions
+112
-12
scroll_physics.dart
packages/flutter/lib/src/widgets/scroll_physics.dart
+19
-9
range_maintaining_scroll_physics_test.dart
...r/test/widgets/range_maintaining_scroll_physics_test.dart
+77
-1
scroll_activity_test.dart
packages/flutter/test/widgets/scroll_activity_test.dart
+16
-2
No files found.
packages/flutter/lib/src/widgets/scroll_physics.dart
View file @
3f812722
...
...
@@ -428,8 +428,12 @@ class ScrollPhysics {
/// Scroll physics that attempt to keep the scroll position in range when the
/// contents change dimensions suddenly.
///
/// If the scroll position is already out of range, this attempts to maintain
/// the amount of overscroll or underscroll already present.
/// This attempts to maintain the amount of overscroll or underscroll already present,
/// if the scroll position is already out of range _and_ the extents
/// have decreased, meaning that some content was removed. The reason for this
/// condition is that when new content is added, keeping the same overscroll
/// would mean that instead of showing it to the user, all of it is
/// being skipped by jumping right to the max extent.
///
/// If the scroll activity is animating the scroll position, sudden changes to
/// the scroll dimensions are allowed to happen (so as to prevent animations
...
...
@@ -513,9 +517,9 @@ class RangeMaintainingScrollPhysics extends ScrollPhysics {
maintainOverscroll
=
false
;
if
(
oldPosition
.
minScrollExtent
.
isFinite
&&
oldPosition
.
maxScrollExtent
.
isFinite
&&
newPosition
.
minScrollExtent
.
isFinite
&&
newPosition
.
maxScrollExtent
.
isFinite
)
{
// In addition, if the position changed then we
only enforce
//
the new boundary if the previous boundary was not entirely
//
finite.
A common case where the position changes while one
// In addition, if the position changed then we
don't enforce the new
//
boundary if both the new and previous boundaries are entirely finite.
// A common case where the position changes while one
// of the extents is infinite is a lazily-loaded list. (If the
// boundaries were finite, and the position changed, then we
// assume it was intentional.)
...
...
@@ -529,13 +533,19 @@ class RangeMaintainingScrollPhysics extends ScrollPhysics {
enforceBoundary
=
false
;
}
if
(
maintainOverscroll
)
{
// Force the new position to be no more out of range
// than it was before, if it was overscrolled.
if
(
oldPosition
.
pixels
<
oldPosition
.
minScrollExtent
)
{
// Force the new position to be no more out of range than it was before, if:
// * it was overscrolled, and
// * the extents have decreased, meaning that some content was removed. The
// reason for this condition is that when new content is added, keeping
// the same overscroll would mean that instead of showing it to the user,
// all of it is being skipped by jumping right to the max extent.
if
(
oldPosition
.
pixels
<
oldPosition
.
minScrollExtent
&&
newPosition
.
minScrollExtent
>
oldPosition
.
minScrollExtent
)
{
final
double
oldDelta
=
oldPosition
.
minScrollExtent
-
oldPosition
.
pixels
;
return
newPosition
.
minScrollExtent
-
oldDelta
;
}
if
(
oldPosition
.
pixels
>
oldPosition
.
maxScrollExtent
)
{
if
(
oldPosition
.
pixels
>
oldPosition
.
maxScrollExtent
&&
newPosition
.
maxScrollExtent
<
oldPosition
.
maxScrollExtent
)
{
final
double
oldDelta
=
oldPosition
.
pixels
-
oldPosition
.
maxScrollExtent
;
return
newPosition
.
maxScrollExtent
+
oldDelta
;
}
...
...
packages/flutter/test/widgets/range_maintaining_scroll_physics_test.dart
View file @
3f812722
...
...
@@ -230,7 +230,7 @@ void main() {
expect
(
bike2
.
center
,
bike1
.
shift
(
const
Offset
(
100.0
,
0.0
)).
center
);
});
testWidgets
(
'
Changing the size of the viewport while you are overdragg
ed'
,
(
WidgetTester
tester
)
async
{
testWidgets
(
'
changing the size of the viewport when overscroll
ed'
,
(
WidgetTester
tester
)
async
{
Widget
build
(
double
height
)
{
return
Directionality
(
textDirection:
TextDirection
.
rtl
,
...
...
@@ -263,6 +263,82 @@ void main() {
final
Rect
newPosition
=
tester
.
getRect
(
find
.
byType
(
Placeholder
));
expect
(
oldPosition
,
newPosition
);
});
testWidgets
(
'inserting and removing an item when overscrolled'
,
(
WidgetTester
tester
)
async
{
// Regression test for https://github.com/flutter/flutter/issues/62890
const
double
itemExtent
=
100.0
;
final
UniqueKey
key
=
UniqueKey
();
final
Finder
finder
=
find
.
byKey
(
key
);
Widget
build
({
required
bool
twoItems
})
{
return
Directionality
(
textDirection:
TextDirection
.
rtl
,
child:
ScrollConfiguration
(
behavior:
const
RangeMaintainingTestScrollBehavior
(),
child:
Align
(
child:
SizedBox
(
width:
100.0
,
height:
100.0
,
child:
ListView
(
children:
<
Widget
>[
SizedBox
(
height:
itemExtent
,
child:
Placeholder
(
key:
key
)),
if
(
twoItems
)
const
SizedBox
(
height:
itemExtent
,
child:
Placeholder
()),
],
),
),
),
),
);
}
await
tester
.
pumpWidget
(
build
(
twoItems:
false
));
final
ScrollPosition
position
=
tester
.
state
<
ScrollableState
>(
find
.
byType
(
Scrollable
)).
position
;
// overscroll bottom
final
TestGesture
drag1
=
await
tester
.
startGesture
(
tester
.
getCenter
(
finder
));
await
tester
.
pump
();
await
drag1
.
moveBy
(
const
Offset
(
0.0
,
-
50.0
));
await
tester
.
pump
();
final
double
oldOverscroll1
=
position
.
pixels
-
position
.
maxScrollExtent
;
final
Rect
oldPosition1
=
tester
.
getRect
(
finder
);
await
tester
.
pumpWidget
(
build
(
twoItems:
true
));
// verify inserting new item didn't change the position of the first one
expect
(
oldPosition1
,
tester
.
getRect
(
finder
));
// verify the overscroll changed by the size of the added item
final
double
newOverscroll1
=
position
.
pixels
-
position
.
maxScrollExtent
;
expect
(
oldOverscroll1
,
isPositive
);
expect
(
newOverscroll1
,
isNegative
);
expect
(
newOverscroll1
,
oldOverscroll1
-
itemExtent
);
await
drag1
.
up
();
// verify there's no ballistic animation, because we weren't overscrolled
expect
(
await
tester
.
pumpAndSettle
(),
1
);
// overscroll bottom
final
TestGesture
drag2
=
await
tester
.
startGesture
(
tester
.
getCenter
(
finder
));
await
tester
.
pump
();
await
drag2
.
moveBy
(
const
Offset
(
0.0
,
-
100.0
));
await
tester
.
pump
();
final
double
oldOverscroll2
=
position
.
pixels
-
position
.
maxScrollExtent
;
// should find nothing because item is not visible
expect
(
finder
,
findsNothing
);
await
tester
.
pumpWidget
(
build
(
twoItems:
false
));
// verify removing an item changed the position of the first one, because prior it was not visible
expect
(
oldPosition1
,
tester
.
getRect
(
finder
));
// verify the overscroll was maintained
final
double
newOverscroll2
=
position
.
pixels
-
position
.
maxScrollExtent
;
expect
(
oldOverscroll2
,
isPositive
);
expect
(
oldOverscroll2
,
newOverscroll2
);
await
drag2
.
up
();
// verify there's a ballistic animation from overscroll
expect
(
await
tester
.
pumpAndSettle
(),
9
);
});
}
class
TabBarDemo
extends
StatelessWidget
{
...
...
packages/flutter/test/widgets/scroll_activity_test.dart
View file @
3f812722
...
...
@@ -13,7 +13,7 @@ List<Widget> children(int n) {
}
void
main
(
)
{
testWidgets
(
'Scrolling with list view changes'
,
(
WidgetTester
tester
)
async
{
testWidgets
(
'Scrolling with list view changes
, leaving the overscroll
'
,
(
WidgetTester
tester
)
async
{
final
ScrollController
controller
=
ScrollController
();
await
tester
.
pumpWidget
(
MaterialApp
(
home:
ListView
(
controller:
controller
,
children:
children
(
30
))));
final
double
thirty
=
controller
.
position
.
maxScrollExtent
;
...
...
@@ -22,7 +22,21 @@ void main() {
controller
.
jumpTo
(
thirty
+
100.0
);
// past the end
await
tester
.
pump
();
await
tester
.
pumpWidget
(
MaterialApp
(
home:
ListView
(
controller:
controller
,
children:
children
(
31
))));
expect
(
controller
.
position
.
pixels
,
thirty
+
200.0
);
// same distance past the end
expect
(
controller
.
position
.
pixels
,
thirty
+
100.0
);
// has the same position, but no longer overscrolled
expect
(
await
tester
.
pumpAndSettle
(),
1
);
// doesn't have ballistic animation...
expect
(
controller
.
position
.
pixels
,
thirty
+
100.0
);
// and ends up at the end
});
testWidgets
(
'Scrolling with list view changes, remaining overscrolled'
,
(
WidgetTester
tester
)
async
{
final
ScrollController
controller
=
ScrollController
();
await
tester
.
pumpWidget
(
MaterialApp
(
home:
ListView
(
controller:
controller
,
children:
children
(
30
))));
final
double
thirty
=
controller
.
position
.
maxScrollExtent
;
controller
.
jumpTo
(
thirty
);
await
tester
.
pump
();
controller
.
jumpTo
(
thirty
+
200.0
);
// past the end
await
tester
.
pump
();
await
tester
.
pumpWidget
(
MaterialApp
(
home:
ListView
(
controller:
controller
,
children:
children
(
31
))));
expect
(
controller
.
position
.
pixels
,
thirty
+
200.0
);
// has the same position, still overscrolled
expect
(
await
tester
.
pumpAndSettle
(),
8
);
// now it goes ballistic...
expect
(
controller
.
position
.
pixels
,
thirty
+
100.0
);
// and ends up at the end
});
...
...
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