Unverified Commit be0076f3 authored by Kate Lovett's avatar Kate Lovett Committed by GitHub

Prioritize scrolling away nested overscroll (#55069)

parent c849ffd3
......@@ -909,21 +909,31 @@ class _NestedScrollCoordinator implements ScrollActivityDelegate, ScrollHoldCont
if (_innerPositions.isEmpty) {
_outerPosition.applyFullDragUpdate(delta);
} else if (delta < 0.0) {
// dragging "up"
// TODO(ianh): prioritize first getting rid of overscroll, and then the
// outer view, so that the app bar will scroll out of the way asap.
// Right now we ignore overscroll. This works fine on Android but looks
// weird on iOS if you fling down then up. The problem is it's not at all
// clear what this should do when you have multiple inner positions at
// different levels of overscroll.
final double innerDelta = _outerPosition.applyClampedDragUpdate(delta);
if (innerDelta != 0.0) {
for (final _NestedScrollPosition position in _innerPositions)
position.applyFullDragUpdate(innerDelta);
// Dragging "up"
// Prioritize getting rid of any inner overscroll, and then the outer
// view, so that the app bar will scroll out of the way asap.
double outerDelta = delta;
for (final _NestedScrollPosition position in _innerPositions) {
if (position.pixels < 0.0) { // This inner position is in overscroll.
final double potentialOuterDelta = position.applyClampedDragUpdate(delta);
// In case there are multiple positions in varying states of
// overscroll, the first to 'reach' the outer view above takes
// precedence.
outerDelta = math.max(outerDelta, potentialOuterDelta);
}
}
if (outerDelta != 0.0) {
final double innerDelta = _outerPosition.applyClampedDragUpdate(
outerDelta
);
if (innerDelta != 0.0) {
for (final _NestedScrollPosition position in _innerPositions)
position.applyFullDragUpdate(innerDelta);
}
}
} else {
// dragging "down" - delta is positive
// prioritize the inner views, so that the inner content will move before
// Dragging "down" - delta is positive
// Prioritize the inner views, so that the inner content will move before
// the app bar grows
double outerDelta = 0.0; // it will go positive if it changes
final List<double> overscrolls = <double>[];
......
......@@ -133,9 +133,7 @@ void main() {
await tester.pump(const Duration(milliseconds: 20));
final Offset point2 = tester.getCenter(find.text('aaa1'));
expect(point2.dy, greaterThan(point1.dy));
// TODO(ianh): Once we improve how we handle scrolling down from overscroll,
// the following expectation should switch to 200.0.
expect(tester.renderObject<RenderBox>(find.byType(AppBar)).size.height, 120.0);
expect(tester.renderObject<RenderBox>(find.byType(AppBar)).size.height, 200.0);
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
testWidgets('NestedScrollView overscroll and release and hold', (WidgetTester tester) async {
......@@ -173,7 +171,6 @@ void main() {
await tester.pumpAndSettle();
expect(find.text('aaa2'), findsOneWidget);
},
skip: true, // https://github.com/flutter/flutter/issues/9040
variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
testWidgets('NestedScrollView', (WidgetTester tester) async {
......@@ -780,7 +777,7 @@ void main() {
await tester.pump();
expect(
tester.getRect(find.byKey(key1)),
const Rect.fromLTWH(0.0, -1.0, 800.0, 100.0),
const 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(129.0));
......@@ -788,7 +785,7 @@ void main() {
await tester.pump();
expect(
tester.getRect(find.byKey(key1)),
const Rect.fromLTWH(0.0, -11.0, 800.0, 100.0),
const Rect.fromLTWH(0.0, 0.0, 800.0, 100.0),
);
await gesture.moveBy(const Offset(0.0, 20.0)); // overscroll again
await tester.pump();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment