mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
Prioritize scrolling away nested overscroll (#55069)
This commit is contained in:
parent
c849ffd3b8
commit
be0076f3f9
@ -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() {
|
|||||||
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() {
|
|||||||
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() {
|
|||||||
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() {
|
|||||||
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();
|
||||||
|
Loading…
Reference in New Issue
Block a user