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