Fix visual overflow when overscrolling RenderShrinkWrappingViewport (#91620)
This commit is contained in:
parent
42eb903200
commit
ce4d635aeb
@ -1919,7 +1919,10 @@ class RenderShrinkWrappingViewport extends RenderViewportBase<SliverLogicalConta
|
|||||||
assert(correctedOffset.isFinite);
|
assert(correctedOffset.isFinite);
|
||||||
_maxScrollExtent = 0.0;
|
_maxScrollExtent = 0.0;
|
||||||
_shrinkWrapExtent = 0.0;
|
_shrinkWrapExtent = 0.0;
|
||||||
_hasVisualOverflow = false;
|
// Since the viewport is shrinkwrapped, we know that any negative overscroll
|
||||||
|
// into the potentially infinite mainAxisExtent will overflow the end of
|
||||||
|
// the viewport.
|
||||||
|
_hasVisualOverflow = correctedOffset < 0.0;
|
||||||
switch (cacheExtentStyle) {
|
switch (cacheExtentStyle) {
|
||||||
case CacheExtentStyle.pixel:
|
case CacheExtentStyle.pixel:
|
||||||
_calculatedCacheExtent = cacheExtent;
|
_calculatedCacheExtent = cacheExtent;
|
||||||
@ -1928,6 +1931,7 @@ class RenderShrinkWrappingViewport extends RenderViewportBase<SliverLogicalConta
|
|||||||
_calculatedCacheExtent = mainAxisExtent * _cacheExtent;
|
_calculatedCacheExtent = mainAxisExtent * _cacheExtent;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return layoutChildSequence(
|
return layoutChildSequence(
|
||||||
child: firstChild,
|
child: firstChild,
|
||||||
scrollOffset: math.max(0.0, correctedOffset),
|
scrollOffset: math.max(0.0, correctedOffset),
|
||||||
|
@ -1846,41 +1846,50 @@ void main() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
Widget _buildShrinkWrap({
|
group('Overscrolling RenderShrinkWrappingViewport', () {
|
||||||
ScrollController? controller,
|
Widget _buildSimpleShrinkWrap({
|
||||||
Axis scrollDirection = Axis.vertical,
|
ScrollController? controller,
|
||||||
ScrollPhysics? physics,
|
Axis scrollDirection = Axis.vertical,
|
||||||
}) {
|
ScrollPhysics? physics,
|
||||||
return Directionality(
|
}) {
|
||||||
textDirection: TextDirection.ltr,
|
return Directionality(
|
||||||
child: MediaQuery(
|
textDirection: TextDirection.ltr,
|
||||||
data: const MediaQueryData(),
|
child: MediaQuery(
|
||||||
child: ListView.builder(
|
data: const MediaQueryData(),
|
||||||
controller: controller,
|
child: ListView.builder(
|
||||||
physics: physics,
|
controller: controller,
|
||||||
scrollDirection: scrollDirection,
|
physics: physics,
|
||||||
shrinkWrap: true,
|
scrollDirection: scrollDirection,
|
||||||
itemBuilder: (BuildContext context, int index) => SizedBox(height: 50, width: 50, child: Text('Item $index')),
|
shrinkWrap: true,
|
||||||
itemCount: 20,
|
itemBuilder: (BuildContext context, int index) => SizedBox(height: 50, width: 50, child: Text('Item $index')),
|
||||||
itemExtent: 50,
|
itemCount: 20,
|
||||||
|
itemExtent: 50,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
);
|
||||||
);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
testWidgets('Constrained Shrinkwrapping viewport will not overflow on overscroll', (WidgetTester tester) async {
|
Widget _buildClippingShrinkWrap(
|
||||||
// Regression test for https://github.com/flutter/flutter/issues/89717
|
ScrollController controller, {
|
||||||
final ScrollController controller = ScrollController();
|
bool constrain = false,
|
||||||
await tester.pumpWidget(
|
}) {
|
||||||
Directionality(
|
return Directionality(
|
||||||
textDirection: TextDirection.ltr,
|
textDirection: TextDirection.ltr,
|
||||||
child: MediaQuery(
|
child: MediaQuery(
|
||||||
data: const MediaQueryData(),
|
data: const MediaQueryData(),
|
||||||
|
child: Container(
|
||||||
|
color: const Color(0xFF000000),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Container(height: 100, color: const Color(0x00000000)),
|
// Translucent boxes above and below the shrinkwrapped viewport
|
||||||
|
// make it easily discernible if the viewport is not being
|
||||||
|
// clipped properly.
|
||||||
|
Opacity(
|
||||||
|
opacity: 0.5,
|
||||||
|
child: Container(height: 100, color: const Color(0xFF00B0FF)),
|
||||||
|
),
|
||||||
Container(
|
Container(
|
||||||
height: 150,
|
height: constrain ? 150 : null,
|
||||||
color: const Color(0xFFF44336),
|
color: const Color(0xFFF44336),
|
||||||
child: ListView.builder(
|
child: ListView.builder(
|
||||||
controller: controller,
|
controller: controller,
|
||||||
@ -1890,189 +1899,230 @@ void main() {
|
|||||||
itemCount: 10,
|
itemCount: 10,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Container(height: 100, color: const Color(0x00000000)),
|
Opacity(
|
||||||
|
opacity: 0.5,
|
||||||
|
child: Container(height: 100, color: const Color(0xFF00B0FF)),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
),
|
||||||
);
|
);
|
||||||
expect(controller.offset, 0.0);
|
}
|
||||||
expect(tester.getTopLeft(find.text('Item 0')).dy, 100.0);
|
|
||||||
|
|
||||||
// Overscroll
|
testWidgets('constrained viewport correctly clips overflow', (WidgetTester tester) async {
|
||||||
final TestGesture overscrollGesture = await tester.startGesture(tester.getCenter(find.text('Item 0')));
|
// Regression test for https://github.com/flutter/flutter/issues/89717
|
||||||
await overscrollGesture.moveBy(const Offset(0, 25));
|
final ScrollController controller = ScrollController();
|
||||||
await tester.pump();
|
await tester.pumpWidget(
|
||||||
expect(controller.offset, -25.0);
|
_buildClippingShrinkWrap(controller, constrain: true)
|
||||||
expect(tester.getTopLeft(find.text('Item 0')).dy, 125.0);
|
);
|
||||||
await expectLater(
|
expect(controller.offset, 0.0);
|
||||||
find.byType(Directionality),
|
expect(tester.getTopLeft(find.text('Item 0')).dy, 100.0);
|
||||||
matchesGoldenFile('shrinkwrapped_overscroll.png'),
|
expect(tester.getTopLeft(find.text('Item 9')).dy, 226.0);
|
||||||
);
|
|
||||||
await overscrollGesture.up();
|
|
||||||
await tester.pumpAndSettle();
|
|
||||||
expect(controller.offset, 0.0);
|
|
||||||
expect(tester.getTopLeft(find.text('Item 0')).dy, 100.0);
|
|
||||||
});
|
|
||||||
|
|
||||||
testWidgets('Shrinkwrap allows overscrolling on default platforms - vertical', (WidgetTester tester) async {
|
// Overscroll
|
||||||
// Regression test for https://github.com/flutter/flutter/issues/10949
|
final TestGesture overscrollGesture = await tester.startGesture(tester.getCenter(find.text('Item 0')));
|
||||||
// Scrollables should overscroll by default on iOS and macOS
|
await overscrollGesture.moveBy(const Offset(0, 100));
|
||||||
final ScrollController controller = ScrollController();
|
await tester.pump();
|
||||||
await tester.pumpWidget(
|
expect(controller.offset, -100.0);
|
||||||
_buildShrinkWrap(controller: controller),
|
expect(tester.getTopLeft(find.text('Item 0')).dy, 200.0);
|
||||||
);
|
await expectLater(
|
||||||
expect(controller.offset, 0.0);
|
find.byType(Directionality),
|
||||||
expect(tester.getTopLeft(find.text('Item 0')).dy, 0.0);
|
matchesGoldenFile('shrinkwrap_clipped_constrained_overscroll.png'),
|
||||||
// Check overscroll at both ends
|
);
|
||||||
// Start
|
await overscrollGesture.up();
|
||||||
TestGesture overscrollGesture = await tester.startGesture(tester.getCenter(find.byType(ListView)));
|
await tester.pumpAndSettle();
|
||||||
await overscrollGesture.moveBy(const Offset(0, 25));
|
expect(controller.offset, 0.0);
|
||||||
await tester.pump();
|
expect(tester.getTopLeft(find.text('Item 0')).dy, 100.0);
|
||||||
expect(controller.offset, -25.0);
|
expect(tester.getTopLeft(find.text('Item 9')).dy, 226.0);
|
||||||
expect(tester.getTopLeft(find.text('Item 0')).dy, 25.0);
|
});
|
||||||
await overscrollGesture.up();
|
|
||||||
await tester.pumpAndSettle();
|
|
||||||
expect(controller.offset, 0.0);
|
|
||||||
expect(tester.getTopLeft(find.text('Item 0')).dy, 0.0);
|
|
||||||
|
|
||||||
// End
|
testWidgets('correctly clips overflow without constraints', (WidgetTester tester) async {
|
||||||
final double maxExtent = controller.position.maxScrollExtent;
|
// Regression test for https://github.com/flutter/flutter/issues/89717
|
||||||
controller.jumpTo(controller.position.maxScrollExtent);
|
final ScrollController controller = ScrollController();
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpWidget(
|
||||||
expect(controller.offset, maxExtent);
|
_buildClippingShrinkWrap(controller)
|
||||||
expect(tester.getBottomLeft(find.text('Item 19')).dy, 600.0);
|
);
|
||||||
|
expect(controller.offset, 0.0);
|
||||||
|
expect(tester.getTopLeft(find.text('Item 0')).dy, 100.0);
|
||||||
|
expect(tester.getTopLeft(find.text('Item 9')).dy, 226.0);
|
||||||
|
|
||||||
overscrollGesture = await tester.startGesture(tester.getCenter(find.byType(ListView)));
|
// Overscroll
|
||||||
await overscrollGesture.moveBy(const Offset(0, -25));
|
final TestGesture overscrollGesture = await tester.startGesture(tester.getCenter(find.text('Item 0')));
|
||||||
await tester.pump();
|
await overscrollGesture.moveBy(const Offset(0, 100));
|
||||||
expect(controller.offset, greaterThan(maxExtent));
|
await tester.pump();
|
||||||
expect(tester.getBottomLeft(find.text('Item 19')).dy, 575.0);
|
expect(controller.offset, -100.0);
|
||||||
await overscrollGesture.up();
|
expect(tester.getTopLeft(find.text('Item 0')).dy, 200.0);
|
||||||
await tester.pumpAndSettle();
|
await expectLater(
|
||||||
expect(controller.offset, maxExtent);
|
find.byType(Directionality),
|
||||||
expect(tester.getBottomLeft(find.text('Item 19')).dy, 600.0);
|
matchesGoldenFile('shrinkwrap_clipped_overscroll.png'),
|
||||||
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
|
);
|
||||||
|
await overscrollGesture.up();
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
expect(controller.offset, 0.0);
|
||||||
|
expect(tester.getTopLeft(find.text('Item 0')).dy, 100.0);
|
||||||
|
expect(tester.getTopLeft(find.text('Item 9')).dy, 226.0);
|
||||||
|
});
|
||||||
|
|
||||||
testWidgets('Shrinkwrap allows overscrolling on default platforms - horizontal', (WidgetTester tester) async {
|
testWidgets('allows overscrolling on default platforms - vertical', (WidgetTester tester) async {
|
||||||
// Regression test for https://github.com/flutter/flutter/issues/10949
|
// Regression test for https://github.com/flutter/flutter/issues/10949
|
||||||
// Scrollables should overscroll by default on iOS and macOS
|
// Scrollables should overscroll by default on iOS and macOS
|
||||||
final ScrollController controller = ScrollController();
|
final ScrollController controller = ScrollController();
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
_buildShrinkWrap(controller: controller, scrollDirection: Axis.horizontal),
|
_buildSimpleShrinkWrap(controller: controller),
|
||||||
);
|
);
|
||||||
expect(controller.offset, 0.0);
|
expect(controller.offset, 0.0);
|
||||||
expect(tester.getTopLeft(find.text('Item 0')).dx, 0.0);
|
expect(tester.getTopLeft(find.text('Item 0')).dy, 0.0);
|
||||||
// Check overscroll at both ends
|
// Check overscroll at both ends
|
||||||
// Start
|
// Start
|
||||||
TestGesture overscrollGesture = await tester.startGesture(tester.getCenter(find.byType(ListView)));
|
TestGesture overscrollGesture = await tester.startGesture(tester.getCenter(find.byType(ListView)));
|
||||||
await overscrollGesture.moveBy(const Offset(25, 0));
|
await overscrollGesture.moveBy(const Offset(0, 25));
|
||||||
await tester.pump();
|
await tester.pump();
|
||||||
expect(controller.offset, -25.0);
|
expect(controller.offset, -25.0);
|
||||||
expect(tester.getTopLeft(find.text('Item 0')).dx, 25.0);
|
expect(tester.getTopLeft(find.text('Item 0')).dy, 25.0);
|
||||||
await overscrollGesture.up();
|
await overscrollGesture.up();
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
expect(controller.offset, 0.0);
|
expect(controller.offset, 0.0);
|
||||||
expect(tester.getTopLeft(find.text('Item 0')).dx, 0.0);
|
expect(tester.getTopLeft(find.text('Item 0')).dy, 0.0);
|
||||||
|
|
||||||
// End
|
// End
|
||||||
final double maxExtent = controller.position.maxScrollExtent;
|
final double maxExtent = controller.position.maxScrollExtent;
|
||||||
controller.jumpTo(controller.position.maxScrollExtent);
|
controller.jumpTo(controller.position.maxScrollExtent);
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
expect(controller.offset, maxExtent);
|
expect(controller.offset, maxExtent);
|
||||||
expect(tester.getTopRight(find.text('Item 19')).dx, 800.0);
|
expect(tester.getBottomLeft(find.text('Item 19')).dy, 600.0);
|
||||||
|
|
||||||
overscrollGesture = await tester.startGesture(tester.getCenter(find.byType(ListView)));
|
overscrollGesture = await tester.startGesture(tester.getCenter(find.byType(ListView)));
|
||||||
await overscrollGesture.moveBy(const Offset(-25, 0));
|
await overscrollGesture.moveBy(const Offset(0, -25));
|
||||||
await tester.pump();
|
await tester.pump();
|
||||||
expect(controller.offset, greaterThan(maxExtent));
|
expect(controller.offset, greaterThan(maxExtent));
|
||||||
expect(tester.getTopRight(find.text('Item 19')).dx, 775.0);
|
expect(tester.getBottomLeft(find.text('Item 19')).dy, 575.0);
|
||||||
await overscrollGesture.up();
|
await overscrollGesture.up();
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
expect(controller.offset, maxExtent);
|
expect(controller.offset, maxExtent);
|
||||||
expect(tester.getTopRight(find.text('Item 19')).dx, 800.0);
|
expect(tester.getBottomLeft(find.text('Item 19')).dy, 600.0);
|
||||||
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
|
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
|
||||||
|
|
||||||
testWidgets('Shrinkwrap allows overscrolling per physics - vertical', (WidgetTester tester) async {
|
testWidgets('allows overscrolling on default platforms - horizontal', (WidgetTester tester) async {
|
||||||
// Regression test for https://github.com/flutter/flutter/issues/10949
|
// Regression test for https://github.com/flutter/flutter/issues/10949
|
||||||
// Scrollables should overscroll when the scroll physics allow
|
// Scrollables should overscroll by default on iOS and macOS
|
||||||
final ScrollController controller = ScrollController();
|
final ScrollController controller = ScrollController();
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
_buildShrinkWrap(controller: controller, physics: const BouncingScrollPhysics()),
|
_buildSimpleShrinkWrap(controller: controller, scrollDirection: Axis.horizontal),
|
||||||
);
|
);
|
||||||
expect(controller.offset, 0.0);
|
expect(controller.offset, 0.0);
|
||||||
expect(tester.getTopLeft(find.text('Item 0')).dy, 0.0);
|
expect(tester.getTopLeft(find.text('Item 0')).dx, 0.0);
|
||||||
// Check overscroll at both ends
|
// Check overscroll at both ends
|
||||||
// Start
|
// Start
|
||||||
TestGesture overscrollGesture = await tester.startGesture(tester.getCenter(find.byType(ListView)));
|
TestGesture overscrollGesture = await tester.startGesture(tester.getCenter(find.byType(ListView)));
|
||||||
await overscrollGesture.moveBy(const Offset(0, 25));
|
await overscrollGesture.moveBy(const Offset(25, 0));
|
||||||
await tester.pump();
|
await tester.pump();
|
||||||
expect(controller.offset, -25.0);
|
expect(controller.offset, -25.0);
|
||||||
expect(tester.getTopLeft(find.text('Item 0')).dy, 25.0);
|
expect(tester.getTopLeft(find.text('Item 0')).dx, 25.0);
|
||||||
await overscrollGesture.up();
|
await overscrollGesture.up();
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
expect(controller.offset, 0.0);
|
expect(controller.offset, 0.0);
|
||||||
expect(tester.getTopLeft(find.text('Item 0')).dy, 0.0);
|
expect(tester.getTopLeft(find.text('Item 0')).dx, 0.0);
|
||||||
|
|
||||||
// End
|
// End
|
||||||
final double maxExtent = controller.position.maxScrollExtent;
|
final double maxExtent = controller.position.maxScrollExtent;
|
||||||
controller.jumpTo(controller.position.maxScrollExtent);
|
controller.jumpTo(controller.position.maxScrollExtent);
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
expect(controller.offset, maxExtent);
|
expect(controller.offset, maxExtent);
|
||||||
expect(tester.getBottomLeft(find.text('Item 19')).dy, 600.0);
|
expect(tester.getTopRight(find.text('Item 19')).dx, 800.0);
|
||||||
|
|
||||||
overscrollGesture = await tester.startGesture(tester.getCenter(find.byType(ListView)));
|
overscrollGesture = await tester.startGesture(tester.getCenter(find.byType(ListView)));
|
||||||
await overscrollGesture.moveBy(const Offset(0, -25));
|
await overscrollGesture.moveBy(const Offset(-25, 0));
|
||||||
await tester.pump();
|
await tester.pump();
|
||||||
expect(controller.offset, greaterThan(maxExtent));
|
expect(controller.offset, greaterThan(maxExtent));
|
||||||
expect(tester.getBottomLeft(find.text('Item 19')).dy, 575.0);
|
expect(tester.getTopRight(find.text('Item 19')).dx, 775.0);
|
||||||
await overscrollGesture.up();
|
await overscrollGesture.up();
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
expect(controller.offset, maxExtent);
|
expect(controller.offset, maxExtent);
|
||||||
expect(tester.getBottomLeft(find.text('Item 19')).dy, 600.0);
|
expect(tester.getTopRight(find.text('Item 19')).dx, 800.0);
|
||||||
});
|
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
|
||||||
|
|
||||||
testWidgets('Shrinkwrap allows overscrolling per physics - horizontal', (WidgetTester tester) async {
|
testWidgets('allows overscrolling per physics - vertical', (WidgetTester tester) async {
|
||||||
// Regression test for https://github.com/flutter/flutter/issues/10949
|
// Regression test for https://github.com/flutter/flutter/issues/10949
|
||||||
// Scrollables should overscroll when the scroll physics allow
|
// Scrollables should overscroll when the scroll physics allow
|
||||||
final ScrollController controller = ScrollController();
|
final ScrollController controller = ScrollController();
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
_buildShrinkWrap(
|
_buildSimpleShrinkWrap(controller: controller, physics: const BouncingScrollPhysics()),
|
||||||
controller: controller,
|
);
|
||||||
scrollDirection: Axis.horizontal,
|
expect(controller.offset, 0.0);
|
||||||
physics: const BouncingScrollPhysics(),
|
expect(tester.getTopLeft(find.text('Item 0')).dy, 0.0);
|
||||||
),
|
// Check overscroll at both ends
|
||||||
);
|
// Start
|
||||||
expect(controller.offset, 0.0);
|
TestGesture overscrollGesture = await tester.startGesture(tester.getCenter(find.byType(ListView)));
|
||||||
expect(tester.getTopLeft(find.text('Item 0')).dx, 0.0);
|
await overscrollGesture.moveBy(const Offset(0, 25));
|
||||||
// Check overscroll at both ends
|
await tester.pump();
|
||||||
// Start
|
expect(controller.offset, -25.0);
|
||||||
TestGesture overscrollGesture = await tester.startGesture(tester.getCenter(find.byType(ListView)));
|
expect(tester.getTopLeft(find.text('Item 0')).dy, 25.0);
|
||||||
await overscrollGesture.moveBy(const Offset(25, 0));
|
await overscrollGesture.up();
|
||||||
await tester.pump();
|
await tester.pumpAndSettle();
|
||||||
expect(controller.offset, -25.0);
|
expect(controller.offset, 0.0);
|
||||||
expect(tester.getTopLeft(find.text('Item 0')).dx, 25.0);
|
expect(tester.getTopLeft(find.text('Item 0')).dy, 0.0);
|
||||||
await overscrollGesture.up();
|
|
||||||
await tester.pumpAndSettle();
|
|
||||||
expect(controller.offset, 0.0);
|
|
||||||
expect(tester.getTopLeft(find.text('Item 0')).dx, 0.0);
|
|
||||||
|
|
||||||
// End
|
// End
|
||||||
final double maxExtent = controller.position.maxScrollExtent;
|
final double maxExtent = controller.position.maxScrollExtent;
|
||||||
controller.jumpTo(controller.position.maxScrollExtent);
|
controller.jumpTo(controller.position.maxScrollExtent);
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
expect(controller.offset, maxExtent);
|
expect(controller.offset, maxExtent);
|
||||||
expect(tester.getTopRight(find.text('Item 19')).dx, 800.0);
|
expect(tester.getBottomLeft(find.text('Item 19')).dy, 600.0);
|
||||||
|
|
||||||
overscrollGesture = await tester.startGesture(tester.getCenter(find.byType(ListView)));
|
overscrollGesture = await tester.startGesture(tester.getCenter(find.byType(ListView)));
|
||||||
await overscrollGesture.moveBy(const Offset(-25, 0));
|
await overscrollGesture.moveBy(const Offset(0, -25));
|
||||||
await tester.pump();
|
await tester.pump();
|
||||||
expect(controller.offset, greaterThan(maxExtent));
|
expect(controller.offset, greaterThan(maxExtent));
|
||||||
expect(tester.getTopRight(find.text('Item 19')).dx, 775.0);
|
expect(tester.getBottomLeft(find.text('Item 19')).dy, 575.0);
|
||||||
await overscrollGesture.up();
|
await overscrollGesture.up();
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
expect(controller.offset, maxExtent);
|
expect(controller.offset, maxExtent);
|
||||||
expect(tester.getTopRight(find.text('Item 19')).dx, 800.0);
|
expect(tester.getBottomLeft(find.text('Item 19')).dy, 600.0);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('allows overscrolling per physics - horizontal', (WidgetTester tester) async {
|
||||||
|
// Regression test for https://github.com/flutter/flutter/issues/10949
|
||||||
|
// Scrollables should overscroll when the scroll physics allow
|
||||||
|
final ScrollController controller = ScrollController();
|
||||||
|
await tester.pumpWidget(
|
||||||
|
_buildSimpleShrinkWrap(
|
||||||
|
controller: controller,
|
||||||
|
scrollDirection: Axis.horizontal,
|
||||||
|
physics: const BouncingScrollPhysics(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
expect(controller.offset, 0.0);
|
||||||
|
expect(tester.getTopLeft(find.text('Item 0')).dx, 0.0);
|
||||||
|
// Check overscroll at both ends
|
||||||
|
// Start
|
||||||
|
TestGesture overscrollGesture = await tester.startGesture(tester.getCenter(find.byType(ListView)));
|
||||||
|
await overscrollGesture.moveBy(const Offset(25, 0));
|
||||||
|
await tester.pump();
|
||||||
|
expect(controller.offset, -25.0);
|
||||||
|
expect(tester.getTopLeft(find.text('Item 0')).dx, 25.0);
|
||||||
|
await overscrollGesture.up();
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
expect(controller.offset, 0.0);
|
||||||
|
expect(tester.getTopLeft(find.text('Item 0')).dx, 0.0);
|
||||||
|
|
||||||
|
// End
|
||||||
|
final double maxExtent = controller.position.maxScrollExtent;
|
||||||
|
controller.jumpTo(controller.position.maxScrollExtent);
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
expect(controller.offset, maxExtent);
|
||||||
|
expect(tester.getTopRight(find.text('Item 19')).dx, 800.0);
|
||||||
|
|
||||||
|
overscrollGesture = await tester.startGesture(tester.getCenter(find.byType(ListView)));
|
||||||
|
await overscrollGesture.moveBy(const Offset(-25, 0));
|
||||||
|
await tester.pump();
|
||||||
|
expect(controller.offset, greaterThan(maxExtent));
|
||||||
|
expect(tester.getTopRight(find.text('Item 19')).dx, 775.0);
|
||||||
|
await overscrollGesture.up();
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
expect(controller.offset, maxExtent);
|
||||||
|
expect(tester.getTopRight(find.text('Item 19')).dx, 800.0);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('Handles infinite constraints when TargetPlatform is iOS or macOS', (WidgetTester tester) async {
|
testWidgets('Handles infinite constraints when TargetPlatform is iOS or macOS', (WidgetTester tester) async {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user