Repository navigation
[material_ui] Fix GridTile crash when the incoming constraints are unbounded - #12586
Conversation
There was a problem hiding this comment.
Code Review
This pull request updates GridTile to size itself to its child when incoming constraints are unbounded, such as inside a horizontally scrolling ListView. This is implemented by setting fit: StackFit.passthrough on the Stack and removing the Positioned.fill wrapper from the child. The changes also include regression tests to verify behavior under both unconstrained and tight constraints, along with a pending changelog entry. There are no review comments, and no additional feedback is provided.
|
Hi @kaluli123123 thanks for porting over. Because of the volume of PRs we receive, we require that contributors use our checklist to guide them through critical steps in creating a Flutter PR. This PR's description is missing that checklist, so it is being marked as a Draft. Please edit the PR description to add the checklist, then ensure that you have completed all of the steps. Once you've done that, please mark the PR as ready for review. If you need help, consider asking for advice on the #hackers-new channel on Discord. Also note, PRs in this repo need to be prepended with the package name they are changing, as in .. "[material_ui] " |
There was a problem hiding this comment.
Code Review
This pull request updates GridTile to size itself to its child when incoming constraints are unbounded (such as in a horizontally scrolling ListView) by setting fit: StackFit.passthrough on the Stack and removing Positioned.fill from the child. It also adds corresponding regression and behavior tests, along with a pending changelog entry. There are no review comments, so I have no feedback to provide.
QuncCccccc
left a comment
There was a problem hiding this comment.
Thanks for porting this! The crash fix makes sense, but I have a concern about backward compatibility.
This changes layout behavior whenever the incoming constraints aren't tight. I verified locally:
Center(
child: ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 200, maxHeight: 150),
child: GridTile(
header: Text('Header'),
footer: Text('Footer'),
child: Container(width: 80, height: 100, color: Colors.red),
),
),
)
Before: GridTile size = Size(200, 150) — the child expanded via Positioned.fill
After: GridTile size = Size(80, 100) — the child shrink-wraps via StackFit.passthrough
The two new tests only cover tight and unbounded constraints, so this case isn't caught. Since GridTile can be used outside GridView (e.g. in Center, Align, Column, Wrap), this could be a visible layout change for existing apps.
Curious about your thoughts.
|
@QuncCccccc Thanks for catching this, you are right that the previous version changed the layout for bounded but loose constraints. I pushed 68b5150, which limits the behavior change to the case that used to crash:
Evidence (all measured locally, Flutter 3.44.7):
I also updated the PR description to reflect the new approach. |
elliette
left a comment
There was a problem hiding this comment.
LGTM with a few testing suggestions. Thank you!
| // The tile used to report zero intrinsic sizes because its child was | ||
| // positioned, which the Stack ignores for intrinsics. Keep doing so. | ||
| @override | ||
| double computeMinIntrinsicWidth(double height) => 0.0; | ||
|
|
||
| @override | ||
| double computeMaxIntrinsicWidth(double height) => 0.0; | ||
|
|
||
| @override | ||
| double computeMinIntrinsicHeight(double width) => 0.0; | ||
|
|
||
| @override | ||
| double computeMaxIntrinsicHeight(double width) => 0.0; |
There was a problem hiding this comment.
Since reporting zero intrinsics is deliberate it would be nice to have a small test for it so a future refactor doesn't change it by accident.
| }); | ||
|
|
||
| // Regression test for https://github.com/flutter/flutter/issues/82055 | ||
| testWidgets('GridTile with header and footer sizes itself to its child when unconstrained', ( |
There was a problem hiding this comment.
Nit: since only the width is unbounded here, maybe change "when unconstrained" to "when the width is unbounded".
GridTile placed every child of its Stack in a Positioned widget, including the tile content. A Stack without any non-positioned child sizes itself to the biggest allowed size, which is infinite along the main axis of an unbounded parent such as a horizontally scrolling ListView. RenderStack then failed its size.isFinite assertion. The tile content is now a non-positioned child of the Stack, and the Stack uses StackFit.passthrough so the content still receives the constraints the tile receives. The tile keeps filling the available space when the incoming constraints are tight (the GridView case), and shrink-wraps its content when they are unbounded instead of crashing. Ported from flutter/flutter#191656, which is blocked by the Material code freeze. Fixes flutter/flutter#82055
Only let the tile shrink-wrap its child along unbounded axes, which is the case that previously crashed. Along bounded axes the child keeps filling the available space, and the tile keeps reporting the same intrinsic sizes as before.
RenderProxyBox.computeDryBaseline forwarded the raw constraints to the child, while performLayout and computeDryLayout tighten the bounded axes. Use the same child constraints for the dry baseline, and add a test that the dry baseline matches the actual baseline under bounded loose constraints.
f5c79f9 to
6ddc5c0
Compare
QuncCccccc
left a comment
There was a problem hiding this comment.
Thanks a lot for the fix! LGTM once the comment below and the comment to add a unit test https://github.com/flutter/packages/pull/12586/changes#r4159616084 are fixed:)
| @override | ||
| Size computeDryLayout(BoxConstraints constraints) { | ||
| final BoxConstraints childConstraints = _fillBoundedAxes(constraints); | ||
| return constraints.constrain( |
There was a problem hiding this comment.
getDryLayout now asks the child, and main didn't. So for a tile with a header or footer whose child can't compute a dry layout (for example a LayoutBuilder), getDryLayout now throws instead of returning the full size of the constraints, as main does. This is rare (a GridView never asks for a dry layout), but when both axes are bounded the size is already known, so returning early in computeDryLayout would keep the old behavior:
| return constraints.constrain( | |
| if (childConstraints.isTight) { | |
| return childConstraints.smallest; | |
| } | |
| return constraints.constrain( |
There was a problem hiding this comment.
Fixed in 0f5a19a. computeDryLayout now returns the known size immediately when filling the bounded axes produces tight constraints, without asking the child for dry layout. Unbounded axes still use the child's dry size.
Added a regression with a LayoutBuilder child and both loose bounded and tight constraints. Before the fix it fails with _RenderLayoutBuilder class does not support dry layout; after the fix it passes. Also added all four zero-intrinsic assertions and renamed the existing regression to specify that only the width is unbounded.
Verification with Flutter 3.47.0 / Dart 3.13:
flutter test test/grid_title_test.dart: 9 passed.- Full
material_uisuite: 8,227 passed, 12 skipped. - Repository
analyze,validate --base-branch origin/main,publish-check, andlicense-checkpassed. The publish dry-run reports an informational hint that this branch's batched version predates the latest published version. - Changed-file formatting and
git diff --checkpassed.
These are local results; current-head CI and maintainer review remain separate gates.
Roll Packages from a1ed23c to da40eaf (33 revisions) flutter/packages@a1ed23c...da40eaf 2026-10-15 tarrinneal@gmail.com [pigeon]add support for sealed classes in native interop (flutter/packages#13175) 2026-10-15 tarrinneal@gmail.com [pigeon] Replace full JNI bindings with stubs for API classes that aren't needed (flutter/packages#13173) 2026-10-14 ksanaullah383.khan@gmail.com [material_ui] Fix self-comparison and assert bugs in semantics_tester (flutter/packages#12722) 2026-10-14 magder@google.com [camera_avfoundation] Replace the deprecated 'videoOrientation' with 'videoRotationAngle' on iOS 17+ (flutter/packages#13247) 2026-10-14 zengyan@88.com [material_ui] Fix GridTile crash when the incoming constraints are unbounded (flutter/packages#12586) 2026-10-14 magder@google.com [in_app_purchase_storekit] Remove unused and deprecated "SKDownload" hosted content (flutter/packages#13222) 2026-10-14 55765052+MohanadAbdallah-mv@users.noreply.github.com [material_ui] Add supportingTextPadding to InputDecorator (flutter/packages#12769) 2026-10-14 37883572+edwin-hollen@users.noreply.github.com [vector_graphics_codec] Add support for encoding and decoding paint blur commands (flutter/packages#13148) 2026-10-14 ketulm8@gmail.com [go_router] Fix redirect zone async error handling (flutter/packages#12836) 2026-10-14 fluttergithubbot@gmail.com Sync release-go_router-18.1.0 to main (flutter/packages#13260) 2026-10-14 fluttergithubbot@gmail.com Sync release-cupertino_ui-1.1.3 to main (flutter/packages#13258) 2026-10-14 lsaudon@gmail.com [material_ui] add enableInlinePrediction parameter to TextFormField (flutter/packages#12793) 2026-10-14 fluttergithubbot@gmail.com Sync release-material_ui-1.7.0 to main (flutter/packages#13259) 2026-10-14 sokolovskyi.konstantin@gmail.com [material_ui] Add the Material shapes. (flutter/packages#12771) 2026-10-14 64028623+Ahtsham0715@users.noreply.github.com [material_ui] Add tertiary tap callbacks to InkResponse and InkWell (flutter/packages#12676) 2026-10-14 engine-flutter-autoroll@skia.org Roll Flutter from 4249ccb to 426be96 (44 revisions) (flutter/packages#13256) 2026-10-14 47866232+chunhtai@users.noreply.github.com [material_ui] fixes expanded state in the a11y_assessment home page dropdown (flutter/packages#13219) 2026-10-14 zhongliu88889@gmail.com [VPAT] Fix semantics in a11y_assessments drawer, radio, and rail demos (flutter/packages#13159) 2026-10-14 5684363+tenninebt@users.noreply.github.com [google_maps_flutter] Add onPointOfInterestTap (flutter/packages#11872) 2026-10-14 Gornivv@gmail.com [go_router] Fix shell route key collisions and dynamic branch updates (flutter/packages#12549) 2026-10-14 engine-flutter-autoroll@skia.org Manual roll Flutter from d03768e to 4249ccb (158 revisions) (flutter/packages#13220) 2026-10-14 okorohelijah@google.com [image_picker_ios] Require Flutter 3.47 / iOS 15 and drop deprecated kUTType code paths (flutter/packages#13224) 2026-10-13 louisehsu@google.com [in_app_purchase_storekit] Fixes Storekit 2 flaky tests (flutter/packages#13213) 2026-10-13 stuartmorgan@google.com [local_auth] Convert Android to new Pigeon suspend support (flutter/packages#12894) 2026-10-13 50643541+Mairramer@users.noreply.github.com [material_ui] Add enabled parameter to DropdownButtonFormField (flutter/packages#12610) 2026-10-13 molchanovia.dev@gmail.com [go_router] Link ShellRoute docs to StatefulShellRoute (flutter/packages#13120) 2026-10-13 jmccandless@google.com FadeForwards page transition performance (flutter/packages#13161) 2026-10-13 101952451+eszter-varga@users.noreply.github.com [in_app_purchase_android] Guard async billing callbacks against duplicate listener responses (flutter/packages#12640) 2026-10-13 victor.orozco@cloudsufi.com [google_sign_in] Remove the Objective-C exception catcher (flutter/packages#13156) 2026-10-13 magder@google.com [camera_avfoundation] Remove availability checks below the package minimum iOS 13 (flutter/packages#13214) 2026-10-13 magder@google.com [google_maps_flutter_ios] Remove iOS 14 availability check from example UI tests (flutter/packages#13218) 2026-10-13 stuartmorgan@google.com [google_sign_in] Convert implementation to Kotlin (flutter/packages#13005) 2026-10-13 victor.orozco@cloudsufi.com [image_picker_ios] PR 2/5 Add a PHImageManager image-data seam and migrate plugin native tests to Swift Testing (flutter/packages#13079) If this roll has caused a breakage, revert this CL and set the roller to dry run mode using the controls here: https://autoroll.skia.org/r/flutter-packages-flutter-autoroll Please CC flutter-ecosystem@google.com on the revert to ensure that a human is aware of the problem. To file a bug in Flutter: https://github.com/flutter/flutter/issues/new/choose To report a problem with the AutoRoller itself, please file a bug: https://issues.skia.org/issues/new?component=1389291&template=1850622 Documentation for the AutoRoller is here: ...
Roll Packages from a1ed23c to da40eaf (33 revisions) flutter/packages@a1ed23c...da40eaf 2026-10-15 tarrinneal@gmail.com [pigeon]add support for sealed classes in native interop (flutter/packages#13175) 2026-10-15 tarrinneal@gmail.com [pigeon] Replace full JNI bindings with stubs for API classes that aren't needed (flutter/packages#13173) 2026-10-14 ksanaullah383.khan@gmail.com [material_ui] Fix self-comparison and assert bugs in semantics_tester (flutter/packages#12722) 2026-10-14 magder@google.com [camera_avfoundation] Replace the deprecated 'videoOrientation' with 'videoRotationAngle' on iOS 17+ (flutter/packages#13247) 2026-10-14 zengyan@88.com [material_ui] Fix GridTile crash when the incoming constraints are unbounded (flutter/packages#12586) 2026-10-14 magder@google.com [in_app_purchase_storekit] Remove unused and deprecated "SKDownload" hosted content (flutter/packages#13222) 2026-10-14 55765052+MohanadAbdallah-mv@users.noreply.github.com [material_ui] Add supportingTextPadding to InputDecorator (flutter/packages#12769) 2026-10-14 37883572+edwin-hollen@users.noreply.github.com [vector_graphics_codec] Add support for encoding and decoding paint blur commands (flutter/packages#13148) 2026-10-14 ketulm8@gmail.com [go_router] Fix redirect zone async error handling (flutter/packages#12836) 2026-10-14 fluttergithubbot@gmail.com Sync release-go_router-18.1.0 to main (flutter/packages#13260) 2026-10-14 fluttergithubbot@gmail.com Sync release-cupertino_ui-1.1.3 to main (flutter/packages#13258) 2026-10-14 lsaudon@gmail.com [material_ui] add enableInlinePrediction parameter to TextFormField (flutter/packages#12793) 2026-10-14 fluttergithubbot@gmail.com Sync release-material_ui-1.7.0 to main (flutter/packages#13259) 2026-10-14 sokolovskyi.konstantin@gmail.com [material_ui] Add the Material shapes. (flutter/packages#12771) 2026-10-14 64028623+Ahtsham0715@users.noreply.github.com [material_ui] Add tertiary tap callbacks to InkResponse and InkWell (flutter/packages#12676) 2026-10-14 engine-flutter-autoroll@skia.org Roll Flutter from 4249ccb to 426be96 (44 revisions) (flutter/packages#13256) 2026-10-14 47866232+chunhtai@users.noreply.github.com [material_ui] fixes expanded state in the a11y_assessment home page dropdown (flutter/packages#13219) 2026-10-14 zhongliu88889@gmail.com [VPAT] Fix semantics in a11y_assessments drawer, radio, and rail demos (flutter/packages#13159) 2026-10-14 5684363+tenninebt@users.noreply.github.com [google_maps_flutter] Add onPointOfInterestTap (flutter/packages#11872) 2026-10-14 Gornivv@gmail.com [go_router] Fix shell route key collisions and dynamic branch updates (flutter/packages#12549) 2026-10-14 engine-flutter-autoroll@skia.org Manual roll Flutter from d03768e to 4249ccb (158 revisions) (flutter/packages#13220) 2026-10-14 okorohelijah@google.com [image_picker_ios] Require Flutter 3.47 / iOS 15 and drop deprecated kUTType code paths (flutter/packages#13224) 2026-10-13 louisehsu@google.com [in_app_purchase_storekit] Fixes Storekit 2 flaky tests (flutter/packages#13213) 2026-10-13 stuartmorgan@google.com [local_auth] Convert Android to new Pigeon suspend support (flutter/packages#12894) 2026-10-13 50643541+Mairramer@users.noreply.github.com [material_ui] Add enabled parameter to DropdownButtonFormField (flutter/packages#12610) 2026-10-13 molchanovia.dev@gmail.com [go_router] Link ShellRoute docs to StatefulShellRoute (flutter/packages#13120) 2026-10-13 jmccandless@google.com FadeForwards page transition performance (flutter/packages#13161) 2026-10-13 101952451+eszter-varga@users.noreply.github.com [in_app_purchase_android] Guard async billing callbacks against duplicate listener responses (flutter/packages#12640) 2026-10-13 victor.orozco@cloudsufi.com [google_sign_in] Remove the Objective-C exception catcher (flutter/packages#13156) 2026-10-13 magder@google.com [camera_avfoundation] Remove availability checks below the package minimum iOS 13 (flutter/packages#13214) 2026-10-13 magder@google.com [google_maps_flutter_ios] Remove iOS 14 availability check from example UI tests (flutter/packages#13218) 2026-10-13 stuartmorgan@google.com [google_sign_in] Convert implementation to Kotlin (flutter/packages#13005) 2026-10-13 victor.orozco@cloudsufi.com [image_picker_ios] PR 2/5 Add a PHImageManager image-data seam and migrate plugin native tests to Swift Testing (flutter/packages#13079) If this roll has caused a breakage, revert this CL and set the roller to dry run mode using the controls here: https://autoroll.skia.org/r/flutter-packages-flutter-autoroll Please CC flutter-ecosystem@google.com on the revert to ensure that a human is aware of the problem. To file a bug in Flutter: https://github.com/flutter/flutter/issues/new/choose To report a problem with the AutoRoller itself, please file a bug: https://issues.skia.org/issues/new?component=1389291&template=1850622 Documentation for the AutoRoller is here: ...
Ports flutter/flutter#191656, which is blocked by the Material/Cupertino code freeze in flutter/flutter (see flutter/flutter#188444).
Original description
GridTileplaced every child of itsStackin aPositionedwidget, including the tile content. AStackwithout any non-positioned child sizes itself to the biggest allowed size, which is infinite along the main axis of an unbounded parent such as a horizontally scrollingListView.RenderStackthen failed itssize.isFiniteassertion.The tile content is now a non-positioned child of the
Stack(withStackFit.passthrough), wrapped in a small private render object that makes it fill every bounded axis of the incoming constraints and lets it pick its own size only along unbounded axes. As a result, the layout is unchanged whenever the old code did not crash (tight constraints as inGridView, and bounded but loose constraints such asCenter>ConstrainedBox), including the reported intrinsic sizes, and the tile shrink-wraps its content along an unbounded axis instead of crashing.Fixes flutter/flutter#82055
Test plan
flutter test test/grid_title_test.dartflutter testflutter analyzedart format --output=none --set-exit-if-changed packages/material_ui/lib/src/grid_tile.dart packages/material_ui/test/grid_title_test.dartPre-Review Checklist
[shared_preferences]///).The change uses the repository's pending changelog workflow (
packages/material_ui/pending_changelogs/change_2026_08_25_port191656.yaml). No public API documentation change is needed.Footnotes
Regular contributors who have demonstrated familiarity with the repository guidelines only need to comment if the PR is not auto-exempted by repo tooling. ↩ ↩2