Sitelet https://github.com/flutter/flutter/pull/188626
Skip to content

Fix TreeSliver first node clipping during expand/collapse animation - #188626

Merged
auto-submit[bot] merged 2 commits into
flutter:masterfrom
mbcorona:fix-treesliver-first-node-clip
Jul 29, 2026
Merged

auto-submit[bot] merged 2 commits into
flutter:masterfrom
mbcorona:fix-treesliver-first-node-clip

Conversation

@mbcorona

Copy link
Copy Markdown
Member

Description

While a TreeSliver node expands/collapses, its children should be clipped beneath the node (at the node's trailing edge). This worked for every node except the first: node index 0 clipped at its leading edge, so its children painted over the node during the animation.

The cause was a special case in RenderTreeSliver.paint that conflated "no parent" with "parent is index 0":

(parentIndex == 0 ? 0.0 : itemExtentBuilder(parentIndex, layoutDimensions)!)

This branch only runs for the clipped segments after the first (the first segment is painted unclipped beforehand), so parentIndex is always a real animating parent whose extent must be added — including index 0. The fix always adds the parent's extent.

Demo

Video showing the bug and the fix:

Screen.Recording.2026-06-26.at.7.20.49.a.m.mov

Related Issues

Fixes #188305

Tests

I added the following tests:

Regression tests in sliver_tree_test.dart that pump the toggle animation to its midpoint and assert the clip-rect top edge:

  • First node (index 0) clips at its trailing edge (rowExtent), not 0.0.
  • Non-first node (index 1) clips at its trailing edge (rowExtent * 2), confirming no regression for other nodes.

Pre-launch Checklist

  • I read the [Contributor Guide] and followed the process outlined there for submitting PRs.
  • I read the [AI contribution guidelines] and understand my responsibilities, or I am not using AI tools.
  • I read the [Tree Hygiene] wiki page, which explains my responsibilities.
  • I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement].
  • I signed the [CLA].
  • I listed at least one issue that this PR fixes in the description above.
  • I updated/added relevant documentation (doc comments with ///).
  • I added new tests to check the change I am making, or this PR is [test-exempt].
  • I followed the [breaking change policy] and added [Data Driven Fixes] where supported.
  • All existing and new tests are passing.

@flutter-dashboard flutter-dashboard Bot added the CICD Run CI/CD label Jun 26, 2026
@github-actions github-actions Bot added framework flutter/packages/flutter repository. See also f: labels. f: scrolling Viewports, list views, slivers, etc. labels Jun 26, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates RenderTreeSliver to ensure that the parent node's extent is always added during animation, even when its index is 0, preventing children from painting over it. It also adds regression tests to verify that animating nodes clip their children below their trailing edge. The feedback suggests a more idiomatic and robust way to retrieve the RenderTreeSliver in the tests by using tester.renderObject instead of searching through tester.allRenderObjects.

Comment on lines +1087 to +1089
final RenderTreeSliver renderTree = tester.allRenderObjects
.whereType<RenderTreeSliver>()
.first;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Instead of searching through tester.allRenderObjects, you can use tester.renderObject to directly retrieve the RenderTreeSliver associated with the TreeSliver widget. This is more idiomatic and robust.

      final RenderTreeSliver renderTree = tester.renderObject<RenderTreeSliver>(find.byType(TreeSliver<String>));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are good suggestions. :)

Comment on lines +1105 to +1107
final RenderTreeSliver renderTree = tester.allRenderObjects
.whereType<RenderTreeSliver>()
.first;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Instead of searching through tester.allRenderObjects, you can use tester.renderObject to directly retrieve the RenderTreeSliver associated with the TreeSliver widget. This is more idiomatic and robust.

      final RenderTreeSliver renderTree = tester.renderObject<RenderTreeSliver>(find.byType(TreeSliver<String>));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

++

@mbcorona
mbcorona requested a review from Piinks June 26, 2026 14:06

@Piinks Piinks left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this! Apologies on the review delay, we are finally catching up. 🙏

// parentIndex is always a real animating node (the unclipped first
// segment is already painted), so its extent is added even when it is
// index 0. Otherwise the clip starts at the parent's leading edge and its
// children paint over it. See https://github.com/flutter/flutter/issues/188305.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can remove this reference to the issue, it will be out of date in the future since this change will close it!

Comment on lines +1010 to +1013
// Regression test for https://github.com/flutter/flutter/issues/188305.
// While a node expands, its children must be clipped beneath the node (at the
// node's trailing edge) - including the first node, which used to clip at its
// leading edge and let its children paint over it.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: This can go inside of the group body.

@mbcorona

Copy link
Copy Markdown
Member Author

Hi @Piinks , documentation has been updated :)

@Piinks Piinks left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM thank you!

@Piinks
Piinks force-pushed the fix-treesliver-first-node-clip branch from e35f57f to d9fb52f Compare July 28, 2026 19:50
@Piinks Piinks added the autosubmit Merge PR when tree becomes green via auto submit App label Jul 28, 2026
@auto-submit
auto-submit Bot added this pull request to the merge queue Jul 29, 2026
Merged via the queue into flutter:master with commit 59c14b6 Jul 29, 2026
21 of 22 checks passed
@flutter-dashboard flutter-dashboard Bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Jul 29, 2026
stuartmorgan-g pushed a commit to flutter/packages that referenced this pull request Jul 30, 2026
…12325)

Manual roll requested by stuartmorgan@google.com

flutter/flutter@c83f80b...2a230d1

2026-07-29 zerouali.bardai.omar@gmail.com Clarify CustomScrollView use
cases (flutter/flutter#189692)
2026-07-29 brunocorona.alcantar@gmail.com Fix TreeSliver first node
clipping during expand/collapse animation (flutter/flutter#188626)
2026-07-29 chris@bracken.jp iOS: Migrate VSyncClient tests to Swift
Testing (flutter/flutter#190054)
2026-07-29 32538273+ValentinVignal@users.noreply.github.com Remove no
shuffle from flutter_driver extension_test.dart and mock flutter.process
channel (flutter/flutter#187559)
2026-07-29 52160996+FMorschel@users.noreply.github.com Adds missing
await on `instantiateImageCodecFromBuffer` (flutter/flutter#188910)
2026-07-29 1961493+harryterkelsen@users.noreply.github.com [web] Provide
Content-Length header for CanvasKit files in flutter test
(flutter/flutter#190155)

If this roll has caused a breakage, revert this CL and stop the roller
using the controls here:
https://autoroll.skia.org/r/flutter-packages
Please CC stuartmorgan@google.com on the revert to ensure that a human
is aware of the problem.

To file a bug in Packages:
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:
https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CICD Run CI/CD f: scrolling Viewports, list views, slivers, etc. framework flutter/packages/flutter repository. See also f: labels.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

TreeSliver first node visual bug while collapsing/expanding

2 participants