Unverified Commit 82f6d43b authored by Dan Field's avatar Dan Field Committed by GitHub

Avoid NaN for shrinkwrapping viewports (#46265)

parent 0f705b7e
......@@ -505,7 +505,16 @@ abstract class RenderViewportBase<ParentDataClass extends ContainerParentDataMix
@override
Rect describeApproximatePaintClip(RenderSliver child) {
final Rect viewportClip = Offset.zero & size;
if (child.constraints.overlap == 0) {
// The child's viewportMainAxisExtent can be infinite when a
// RenderShrinkWrappingViewport is given infinite constraints, such as when
// it is the child of a Row or Column (depending on orientation).
//
// For example, a shrink wrapping render sliver may have infinite
// constraints along the viewport's main axis but may also have bouncing
// scroll physics, which will allow for some scrolling effect to occur.
// We should just use the viewportClip - the start of the overlap is at
// double.infinity and so it is effectively meaningless.
if (child.constraints.overlap == 0 || !child.constraints.viewportMainAxisExtent.isFinite) {
return viewportClip;
}
......@@ -1756,6 +1765,11 @@ class RenderShrinkWrappingViewport extends RenderViewportBase<SliverLogicalConta
}
double _attemptLayout(double mainAxisExtent, double crossAxisExtent, double correctedOffset) {
// We can't assert mainAxisExtent is finite, because it could be infinite if
// it is within a column or row for example. In such a case, there's not
// even any scrolling to do, although some scroll physics (i.e.
// BouncingScrollPhysics) could still temporarily scroll the content in a
// simulation.
assert(!mainAxisExtent.isNaN);
assert(mainAxisExtent >= 0.0);
assert(crossAxisExtent.isFinite);
......
......@@ -124,4 +124,47 @@ void main() {
layout(renderViewport);
expect(renderViewport.describeSemanticsClip(null), rectExpandedOnAxis(height * 2.5));
});
test('RenderShrinkWrappingViewport describeApproximatePaintClip with infinite viewportMainAxisExtent returns finite rect', () {
final RenderSliver child = CustomConstraintsRenderSliver(const SliverConstraints(
axisDirection: AxisDirection.down,
cacheOrigin: 0.0,
crossAxisDirection: AxisDirection.left,
crossAxisExtent: 400.0,
growthDirection: GrowthDirection.forward,
overlap: 1.0, // must not equal 0 for this test
precedingScrollExtent: 0.0,
remainingPaintExtent: double.infinity,
remainingCacheExtent: 0.0,
scrollOffset: 0.0,
userScrollDirection: ScrollDirection.idle,
viewportMainAxisExtent: double.infinity, // must == infinity
));
final RenderShrinkWrappingViewport viewport = RenderShrinkWrappingViewport(
crossAxisDirection: AxisDirection.left,
offset: ViewportOffset.zero(),
children: <RenderSliver>[ child ],
);
layout(viewport);
expect(
viewport.describeApproximatePaintClip(child),
const Rect.fromLTRB(0.0, 0.0, 800.0, 600.0),
);
});
}
class CustomConstraintsRenderSliver extends RenderSliver {
CustomConstraintsRenderSliver(this.constraints);
@override
SliverGeometry get geometry => const SliverGeometry();
@override
final SliverConstraints constraints;
@override
void performLayout() {}
}
......@@ -1144,4 +1144,39 @@ void main() {
' its intrinsic dimensions.\n',
);
});
testWidgets('Handles infinite constraints when TargetPlatform is iOS', (WidgetTester tester) async {
// regression test for https://github.com/flutter/flutter/issues/45866
final TargetPlatform oldTargetPlatform = debugDefaultTargetPlatformOverride;
debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
GridView(
shrinkWrap: true,
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
childAspectRatio: 3,
mainAxisSpacing: 3,
crossAxisSpacing: 3),
children: const <Widget>[
Text('a'),
Text('b'),
Text('c'),
],
),
],
),
),
);
expect(find.text('b'), findsOneWidget);
await tester.drag(find.text('b'), const Offset(0, 200));
await tester.pumpAndSettle();
debugDefaultTargetPlatformOverride = oldTargetPlatform;
});
}
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