Fix NestedScrollView inner ballistic activity for 0 velocity (#61386)
This commit is contained in:
parent
563afe381c
commit
16d5dd9b13
@ -918,9 +918,7 @@ class _NestedScrollCoordinator implements ScrollActivityDelegate, ScrollHoldCont
|
||||
ScrollActivity createInnerBallisticScrollActivity(_NestedScrollPosition position, double velocity) {
|
||||
return position.createBallisticScrollActivity(
|
||||
position.physics.createBallisticSimulation(
|
||||
velocity == 0
|
||||
? position as ScrollMetrics
|
||||
: _getMetrics(position, velocity),
|
||||
_getMetrics(position, velocity),
|
||||
velocity,
|
||||
),
|
||||
mode: _NestedBallisticScrollActivityMode.inner,
|
||||
@ -929,7 +927,8 @@ class _NestedScrollCoordinator implements ScrollActivityDelegate, ScrollHoldCont
|
||||
|
||||
_NestedScrollMetrics _getMetrics(_NestedScrollPosition innerPosition, double velocity) {
|
||||
assert(innerPosition != null);
|
||||
double pixels, minRange, maxRange, correctionOffset, extra;
|
||||
double pixels, minRange, maxRange, correctionOffset;
|
||||
double extra = 0.0;
|
||||
if (innerPosition.pixels == innerPosition.minScrollExtent) {
|
||||
pixels = _outerPosition.pixels.clamp(
|
||||
_outerPosition.minScrollExtent,
|
||||
@ -939,7 +938,6 @@ class _NestedScrollCoordinator implements ScrollActivityDelegate, ScrollHoldCont
|
||||
maxRange = _outerPosition.maxScrollExtent;
|
||||
assert(minRange <= maxRange);
|
||||
correctionOffset = 0.0;
|
||||
extra = 0.0;
|
||||
} else {
|
||||
assert(innerPosition.pixels != innerPosition.minScrollExtent);
|
||||
if (innerPosition.pixels < innerPosition.minScrollExtent) {
|
||||
@ -974,8 +972,7 @@ class _NestedScrollCoordinator implements ScrollActivityDelegate, ScrollHoldCont
|
||||
if (velocity > 0.0) {
|
||||
// shrinking
|
||||
extra = _outerPosition.minScrollExtent - _outerPosition.pixels;
|
||||
} else {
|
||||
assert(velocity < 0.0);
|
||||
} else if (velocity < 0.0) {
|
||||
// growing
|
||||
extra = _outerPosition.pixels - (_outerPosition.maxScrollExtent - _outerPosition.minScrollExtent);
|
||||
}
|
||||
|
@ -1817,6 +1817,97 @@ void main() {
|
||||
verifyGeometry(key: appBarKey, paintExtent: 200.0, visible: true);
|
||||
});
|
||||
});
|
||||
|
||||
group('Correctly handles 0 velocity inner ballistic scroll activity:', () {
|
||||
// Regression tests for https://github.com/flutter/flutter/issues/17096
|
||||
Widget _buildBallisticTest(ScrollController controller) {
|
||||
return MaterialApp(
|
||||
home: Scaffold(
|
||||
body: NestedScrollView(
|
||||
controller: controller,
|
||||
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
|
||||
return <Widget>[
|
||||
const SliverAppBar(
|
||||
pinned: true,
|
||||
expandedHeight: 200.0,
|
||||
),
|
||||
];
|
||||
},
|
||||
body: ListView.builder(
|
||||
itemCount: 50,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
return Container(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Text('Item $index'),
|
||||
)
|
||||
);
|
||||
}
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
testWidgets('overscroll, hold for 0 velocity, and release', (WidgetTester tester) async {
|
||||
// Dragging into an overscroll and holding so that when released, the
|
||||
// ballistic scroll activity has a 0 velocity.
|
||||
final ScrollController controller = ScrollController();
|
||||
await tester.pumpWidget(_buildBallisticTest(controller));
|
||||
// Last item of the inner scroll view.
|
||||
expect(find.text('Item 49'), findsNothing);
|
||||
|
||||
// Scroll to bottom
|
||||
await tester.fling(find.text('Item 3'), const Offset(0.0, -50.0), 10000.0);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// End of list
|
||||
expect(find.text('Item 49'), findsOneWidget);
|
||||
expect(tester.getCenter(find.text('Item 49')).dy, equals(585.0));
|
||||
|
||||
// Overscroll, dragging like this will release with 0 velocity.
|
||||
await tester.drag(find.text('Item 49'), const Offset(0.0, -50.0));
|
||||
await tester.pump();
|
||||
// If handled correctly, the last item should still be visible and
|
||||
// progressing back down to the bottom edge, instead of jumping further
|
||||
// up the list and out of view.
|
||||
expect(find.text('Item 49'), findsOneWidget);
|
||||
await tester.pumpAndSettle();
|
||||
expect(tester.getCenter(find.text('Item 49')).dy, equals(585.0));
|
||||
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS }));
|
||||
|
||||
testWidgets('overscroll, release, and tap', (WidgetTester tester) async {
|
||||
// Tapping while an inner ballistic scroll activity is in progress will
|
||||
// trigger a secondary ballistic scroll activity with a 0 velocity.
|
||||
final ScrollController controller = ScrollController();
|
||||
await tester.pumpWidget(_buildBallisticTest(controller));
|
||||
// Last item of the inner scroll view.
|
||||
expect(find.text('Item 49'), findsNothing);
|
||||
|
||||
// Scroll to bottom
|
||||
await tester.fling(find.text('Item 3'), const Offset(0.0, -50.0), 10000.0);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// End of list
|
||||
expect(find.text('Item 49'), findsOneWidget);
|
||||
expect(tester.getCenter(find.text('Item 49')).dy, equals(585.0));
|
||||
|
||||
// Fling again to trigger first ballistic activity.
|
||||
await tester.fling(find.text('Item 48'), const Offset(0.0, -50.0), 10000.0);
|
||||
await tester.pump();
|
||||
|
||||
// Tap after releasing the overscroll to trigger secondary inner ballistic
|
||||
// scroll activity with 0 velocity.
|
||||
await tester.tap(find.text('Item 49'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// If handled correctly, the ballistic scroll activity should finish
|
||||
// closing out the overscrolled area, with the last item visible at the
|
||||
// bottom.
|
||||
expect(find.text('Item 49'), findsOneWidget);
|
||||
expect(tester.getCenter(find.text('Item 49')).dy, equals(585.0));
|
||||
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS }));
|
||||
});
|
||||
}
|
||||
|
||||
class TestHeader extends SliverPersistentHeaderDelegate {
|
||||
|
Loading…
x
Reference in New Issue
Block a user