Skip to content

Eliminate rebuilds for Scaffold FAB animation#182331

Merged
auto-submit[bot] merged 2 commits into
flutter:masterfrom
nate-thegrate:optimized-fab
Mar 4, 2026
Merged

Eliminate rebuilds for Scaffold FAB animation#182331
auto-submit[bot] merged 2 commits into
flutter:masterfrom
nate-thegrate:optimized-fab

Conversation

@nate-thegrate

Copy link
Copy Markdown
Contributor

This PR contains a tweak to the Scaffold widget's internal logic, reducing the amount of work that needs to be performed each time the FAB animation updates.

resolves #182330

@github-actions github-actions Bot added framework flutter/packages/flutter repository. See also f: labels. f: material design flutter/packages/flutter/material repository. labels Feb 12, 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 optimizes the Scaffold widget to prevent unnecessary rebuilds during the Floating Action Button (FAB) animation. The change replaces an AnimatedBuilder with a Builder and passes the FAB's move animation controller directly to the _ScaffoldLayout delegate's relayout property. This ensures that only the layout is updated when the animation ticks, rather than rebuilding a larger portion of the widget tree. A new test has been added to confirm that the widget building the CustomMultiChildLayout is not marked as dirty during the animation, verifying the performance improvement.

@dkwingsmt dkwingsmt 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!

expect(find.byType(FloatingActionButton), findsNothing);
});

testWidgets('Scaffold FAB animates without rebuilding', (WidgetTester tester) async {

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.

Do we have a test to verify that the animation is indeed applied (i.e. relayout: is correctly assigned)?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes we do! I was able to find two tests that cover the FAB animation:

testWidgets('Floating action entrance/exit animation', (WidgetTester tester) async {
await tester.pumpWidget(
const MaterialApp(
home: Scaffold(
floatingActionButton: FloatingActionButton(
key: Key('one'),
onPressed: null,
child: Text('1'),
),
),
),
);
expect(tester.binding.transientCallbackCount, 0);
await tester.pumpWidget(
const MaterialApp(
home: Scaffold(
floatingActionButton: FloatingActionButton(
key: Key('two'),
onPressed: null,
child: Text('2'),
),
),
),
);
expect(tester.binding.transientCallbackCount, greaterThan(0));
await tester.pumpWidget(Container());
expect(tester.binding.transientCallbackCount, 0);
await tester.pumpWidget(const MaterialApp(home: Scaffold()));
expect(tester.binding.transientCallbackCount, 0);
await tester.pumpWidget(
const MaterialApp(
home: Scaffold(
floatingActionButton: FloatingActionButton(
key: Key('one'),
onPressed: null,
child: Text('1'),
),
),
),
);
expect(tester.binding.transientCallbackCount, greaterThan(0));
});

testWidgets('FAB default entrance and exit animations', (WidgetTester tester) async {
var showFab = false;
await tester.pumpWidget(
MaterialApp(
home: StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
return Scaffold(
body: ElevatedButton(
onPressed: () {
setState(() {
showFab = !showFab;
});
},
child: const Text('Toggle FAB'),
),
floatingActionButton: !showFab
? null
: FloatingActionButton(onPressed: () {}, child: const Icon(Icons.add)),
);
},
),
),
);
// FAB is not visible.
expect(find.byType(FloatingActionButton), findsNothing);
// Tap the button to show the FAB.
await tester.tap(find.widgetWithText(ElevatedButton, 'Toggle FAB'));
await tester.pump();
await tester.pump(const Duration(milliseconds: 100)); // Advance the animation by 100ms.
// FAB is partially animated in.
expect(tester.getTopLeft(find.byType(FloatingActionButton)).dx, closeTo(743.8, 0.1));
await tester.pump(const Duration(milliseconds: 100)); // Advance the animation by 100ms.
// FAB is fully animated in.
expect(tester.getTopLeft(find.byType(FloatingActionButton)).dx, equals(728.0));
// Tap the button to hide the FAB.
await tester.tap(find.widgetWithText(ElevatedButton, 'Toggle FAB'));
await tester.pump();
await tester.pump(const Duration(milliseconds: 100)); // Advance the animation by 100ms.
// FAB is partially animated out.
expect(tester.getTopLeft(find.byType(FloatingActionButton)).dx, closeTo(747.1, 0.1));
await tester.pump(const Duration(milliseconds: 100)); // Advance the animation by 100ms.
// FAB is fully animated out.
expect(tester.getTopLeft(find.byType(FloatingActionButton)).dx, equals(756.0));
await tester.pump(const Duration(milliseconds: 50)); // Advance the animation by 50ms.
// FAB is not visible.
expect(find.byType(FloatingActionButton), findsNothing);
});

@nate-thegrate
nate-thegrate force-pushed the optimized-fab branch 2 times, most recently from 8713055 to 9153a79 Compare February 26, 2026 17:16

@justinmc justinmc 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 👍 Good catch!

@justinmc justinmc added the autosubmit Merge PR when tree becomes green via auto submit App label Feb 26, 2026
@auto-submit auto-submit Bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Feb 26, 2026
@auto-submit

auto-submit Bot commented Feb 26, 2026

Copy link
Copy Markdown
Contributor

autosubmit label was removed for flutter/flutter/182331, because - The status or check suite Google testing has failed. Please fix the issues identified (or deflake) before re-applying this label.

@nate-thegrate

Copy link
Copy Markdown
Contributor Author

Dang it, looks like Google Testing failed. I'll re-trigger the checks in hopes that it was a flake…

@nate-thegrate

Copy link
Copy Markdown
Contributor Author

Everything passed! I believe we are ready to land 🫡

@dkwingsmt dkwingsmt added the autosubmit Merge PR when tree becomes green via auto submit App label Mar 4, 2026
@auto-submit
auto-submit Bot added this pull request to the merge queue Mar 4, 2026
Merged via the queue into flutter:master with commit 9a78d7a Mar 4, 2026
73 of 74 checks passed
@flutter-dashboard flutter-dashboard Bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Mar 4, 2026
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 5, 2026
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 5, 2026
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 5, 2026
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 5, 2026
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 6, 2026
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 6, 2026
auto-submit Bot pushed a commit to flutter/packages that referenced this pull request Mar 6, 2026
Roll Flutter from d3dd7744e81f to d18214307703 (33 revisions)

flutter/flutter@d3dd774...d182143

2026-03-06 [email protected] Roll Packages from 8d5c5cd to fe3de64 (2 revisions) (flutter/flutter#183308)
2026-03-06 [email protected] Roll Dart SDK from 1b51451cdb99 to 7c7c1e3d024d (2 revisions) (flutter/flutter#183294)
2026-03-06 [email protected] Roll Dart SDK from 9ac06cdd1801 to 1b51451cdb99 (9 revisions) (flutter/flutter#183289)
2026-03-06 [email protected] Add GitHub workflows to assist with release tasks (flutter/flutter#181978)
2026-03-06 [email protected] [Impeller] Fix new convex path shadow generation in perspective (flutter/flutter#183187)
2026-03-06 [email protected] Roll pub packages (flutter/flutter#183178)
2026-03-05 [email protected] fix: use double quotes in settings.gradle.kts template (flutter/flutter#183081)
2026-03-05 [email protected] Add fallbackColor for PredictiveBackPageTransitionBuilder and PredictiveBackFullscreenPageTransitionBuilder (flutter/flutter#182690)
2026-03-05 [email protected] Simplify TesterContextGLES (multithreading logic not needed), and enable some tests that now pass (flutter/flutter#183250)
2026-03-05 [email protected] Roll Skia from a94df1cdabb0 to a69ef43650ee (14 revisions) (flutter/flutter#183280)
2026-03-05 [email protected] Windowing implementation of `showDialog` that uses a native desktop window to display the content  (flutter/flutter#181861)
2026-03-05 [email protected] Build CocoaPod plugin frameworks for Add to App FlutterPluginRegistrant (flutter/flutter#183239)
2026-03-05 [email protected] Extend the Linux web_skwasm_tests_1 timeout to 45 minutes (flutter/flutter#183247)
2026-03-05 [email protected] Update Dart to 3.12 beta 2 (flutter/flutter#183251)
2026-03-05 [email protected] Replace the rest of the references to `flutter/engine` with `flutter/flutter` (flutter/flutter#182938)
2026-03-05 [email protected] chore: convert android_verified_input to pub-workspace (flutter/flutter#183175)
2026-03-05 [email protected] Add await to flutter_test callsites (flutter/flutter#182983)
2026-03-05 [email protected] [iOS] Skip gesture recognizer reset workaround on iOS 26+  (flutter/flutter#183186)
2026-03-05 [email protected] Add warning for plugins not migrated to UIScene (flutter/flutter#182826)
2026-03-05 [email protected] Roll Fuchsia Linux SDK from JJw5EJ87vLGqFVl4h... to 8ay15_eQOEgPHCypm... (flutter/flutter#183255)
2026-03-05 [email protected] Roll Skia from ada0b7628c79 to a94df1cdabb0 (2 revisions) (flutter/flutter#183249)
2026-03-05 [email protected] Roll Packages from 82baf93 to 8d5c5cd (2 revisions) (flutter/flutter#183269)
2026-03-05 [email protected] Add `UnlabaledLeafNodeEvaluation` (flutter/flutter#182872)
2026-03-04 [email protected] Re-specify the ndk version in various test apps, to prevent ndk download (flutter/flutter#183134)
2026-03-04 [email protected] Eliminate rebuilds for Scaffold FAB animation (flutter/flutter#182331)
2026-03-04 [email protected] Add Michal Kucharski to AUTHORS (flutter/flutter#182366)
2026-03-04 [email protected] Merge changelog from 3.41.4 stable. (flutter/flutter#183243)
2026-03-04 [email protected] Allow stylus support on windows (flutter/flutter#165323)
2026-03-04 [email protected] Fix docs on SingletonFlutterWindow.supportsShowingSystemContextMenu (flutter/flutter#183142)
2026-03-04 [email protected] Roll Packages from 9083bc9 to 82baf93 (5 revisions) (flutter/flutter#183240)
2026-03-04 [email protected] Fixes FocusHighlightMode on Android when typing in software keyboard (flutter/flutter#180753)
2026-03-04 [email protected] Make compileShader() retry without sksl if it fails with sksl. (flutter/flutter#183146)
2026-03-04 [email protected] [web] Use pointer-events: auto for non-interactive leaf semantics nodes (flutter/flutter#183077)

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 [email protected],[email protected] 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:
...
@nate-thegrate
nate-thegrate deleted the optimized-fab branch March 7, 2026 03:10
xxxOVALxxx pushed a commit to xxxOVALxxx/flutter that referenced this pull request Mar 10, 2026
This PR contains a tweak to the Scaffold widget's internal logic,
reducing the amount of work that needs to be performed each time the FAB
animation updates.

resolves flutter#182330
okorohelijah pushed a commit to okorohelijah/packages that referenced this pull request Mar 26, 2026
…r#11191)

Roll Flutter from d3dd7744e81f to d18214307703 (33 revisions)

flutter/flutter@d3dd774...d182143

2026-03-06 [email protected] Roll Packages from 8d5c5cd to fe3de64 (2 revisions) (flutter/flutter#183308)
2026-03-06 [email protected] Roll Dart SDK from 1b51451cdb99 to 7c7c1e3d024d (2 revisions) (flutter/flutter#183294)
2026-03-06 [email protected] Roll Dart SDK from 9ac06cdd1801 to 1b51451cdb99 (9 revisions) (flutter/flutter#183289)
2026-03-06 [email protected] Add GitHub workflows to assist with release tasks (flutter/flutter#181978)
2026-03-06 [email protected] [Impeller] Fix new convex path shadow generation in perspective (flutter/flutter#183187)
2026-03-06 [email protected] Roll pub packages (flutter/flutter#183178)
2026-03-05 [email protected] fix: use double quotes in settings.gradle.kts template (flutter/flutter#183081)
2026-03-05 [email protected] Add fallbackColor for PredictiveBackPageTransitionBuilder and PredictiveBackFullscreenPageTransitionBuilder (flutter/flutter#182690)
2026-03-05 [email protected] Simplify TesterContextGLES (multithreading logic not needed), and enable some tests that now pass (flutter/flutter#183250)
2026-03-05 [email protected] Roll Skia from a94df1cdabb0 to a69ef43650ee (14 revisions) (flutter/flutter#183280)
2026-03-05 [email protected] Windowing implementation of `showDialog` that uses a native desktop window to display the content  (flutter/flutter#181861)
2026-03-05 [email protected] Build CocoaPod plugin frameworks for Add to App FlutterPluginRegistrant (flutter/flutter#183239)
2026-03-05 [email protected] Extend the Linux web_skwasm_tests_1 timeout to 45 minutes (flutter/flutter#183247)
2026-03-05 [email protected] Update Dart to 3.12 beta 2 (flutter/flutter#183251)
2026-03-05 [email protected] Replace the rest of the references to `flutter/engine` with `flutter/flutter` (flutter/flutter#182938)
2026-03-05 [email protected] chore: convert android_verified_input to pub-workspace (flutter/flutter#183175)
2026-03-05 [email protected] Add await to flutter_test callsites (flutter/flutter#182983)
2026-03-05 [email protected] [iOS] Skip gesture recognizer reset workaround on iOS 26+  (flutter/flutter#183186)
2026-03-05 [email protected] Add warning for plugins not migrated to UIScene (flutter/flutter#182826)
2026-03-05 [email protected] Roll Fuchsia Linux SDK from JJw5EJ87vLGqFVl4h... to 8ay15_eQOEgPHCypm... (flutter/flutter#183255)
2026-03-05 [email protected] Roll Skia from ada0b7628c79 to a94df1cdabb0 (2 revisions) (flutter/flutter#183249)
2026-03-05 [email protected] Roll Packages from 82baf93 to 8d5c5cd (2 revisions) (flutter/flutter#183269)
2026-03-05 [email protected] Add `UnlabaledLeafNodeEvaluation` (flutter/flutter#182872)
2026-03-04 [email protected] Re-specify the ndk version in various test apps, to prevent ndk download (flutter/flutter#183134)
2026-03-04 [email protected] Eliminate rebuilds for Scaffold FAB animation (flutter/flutter#182331)
2026-03-04 [email protected] Add Michal Kucharski to AUTHORS (flutter/flutter#182366)
2026-03-04 [email protected] Merge changelog from 3.41.4 stable. (flutter/flutter#183243)
2026-03-04 [email protected] Allow stylus support on windows (flutter/flutter#165323)
2026-03-04 [email protected] Fix docs on SingletonFlutterWindow.supportsShowingSystemContextMenu (flutter/flutter#183142)
2026-03-04 [email protected] Roll Packages from 9083bc9 to 82baf93 (5 revisions) (flutter/flutter#183240)
2026-03-04 [email protected] Fixes FocusHighlightMode on Android when typing in software keyboard (flutter/flutter#180753)
2026-03-04 [email protected] Make compileShader() retry without sksl if it fails with sksl. (flutter/flutter#183146)
2026-03-04 [email protected] [web] Use pointer-events: auto for non-interactive leaf semantics nodes (flutter/flutter#183077)

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 [email protected],[email protected] 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:
...
mboetger pushed a commit to mboetger/flutter that referenced this pull request Mar 26, 2026
This PR contains a tweak to the Scaffold widget's internal logic,
reducing the amount of work that needs to be performed each time the FAB
animation updates.

resolves flutter#182330
creatorpiyush pushed a commit to creatorpiyush/packages that referenced this pull request Jun 10, 2026
…r#11191)

Roll Flutter from d3dd7744e81f to d18214307703 (33 revisions)

flutter/flutter@d3dd774...d182143

2026-03-06 [email protected] Roll Packages from 8d5c5cd to fe3de64 (2 revisions) (flutter/flutter#183308)
2026-03-06 [email protected] Roll Dart SDK from 1b51451cdb99 to 7c7c1e3d024d (2 revisions) (flutter/flutter#183294)
2026-03-06 [email protected] Roll Dart SDK from 9ac06cdd1801 to 1b51451cdb99 (9 revisions) (flutter/flutter#183289)
2026-03-06 [email protected] Add GitHub workflows to assist with release tasks (flutter/flutter#181978)
2026-03-06 [email protected] [Impeller] Fix new convex path shadow generation in perspective (flutter/flutter#183187)
2026-03-06 [email protected] Roll pub packages (flutter/flutter#183178)
2026-03-05 [email protected] fix: use double quotes in settings.gradle.kts template (flutter/flutter#183081)
2026-03-05 [email protected] Add fallbackColor for PredictiveBackPageTransitionBuilder and PredictiveBackFullscreenPageTransitionBuilder (flutter/flutter#182690)
2026-03-05 [email protected] Simplify TesterContextGLES (multithreading logic not needed), and enable some tests that now pass (flutter/flutter#183250)
2026-03-05 [email protected] Roll Skia from a94df1cdabb0 to a69ef43650ee (14 revisions) (flutter/flutter#183280)
2026-03-05 [email protected] Windowing implementation of `showDialog` that uses a native desktop window to display the content  (flutter/flutter#181861)
2026-03-05 [email protected] Build CocoaPod plugin frameworks for Add to App FlutterPluginRegistrant (flutter/flutter#183239)
2026-03-05 [email protected] Extend the Linux web_skwasm_tests_1 timeout to 45 minutes (flutter/flutter#183247)
2026-03-05 [email protected] Update Dart to 3.12 beta 2 (flutter/flutter#183251)
2026-03-05 [email protected] Replace the rest of the references to `flutter/engine` with `flutter/flutter` (flutter/flutter#182938)
2026-03-05 [email protected] chore: convert android_verified_input to pub-workspace (flutter/flutter#183175)
2026-03-05 [email protected] Add await to flutter_test callsites (flutter/flutter#182983)
2026-03-05 [email protected] [iOS] Skip gesture recognizer reset workaround on iOS 26+  (flutter/flutter#183186)
2026-03-05 [email protected] Add warning for plugins not migrated to UIScene (flutter/flutter#182826)
2026-03-05 [email protected] Roll Fuchsia Linux SDK from JJw5EJ87vLGqFVl4h... to 8ay15_eQOEgPHCypm... (flutter/flutter#183255)
2026-03-05 [email protected] Roll Skia from ada0b7628c79 to a94df1cdabb0 (2 revisions) (flutter/flutter#183249)
2026-03-05 [email protected] Roll Packages from 82baf93 to 8d5c5cd (2 revisions) (flutter/flutter#183269)
2026-03-05 [email protected] Add `UnlabaledLeafNodeEvaluation` (flutter/flutter#182872)
2026-03-04 [email protected] Re-specify the ndk version in various test apps, to prevent ndk download (flutter/flutter#183134)
2026-03-04 [email protected] Eliminate rebuilds for Scaffold FAB animation (flutter/flutter#182331)
2026-03-04 [email protected] Add Michal Kucharski to AUTHORS (flutter/flutter#182366)
2026-03-04 [email protected] Merge changelog from 3.41.4 stable. (flutter/flutter#183243)
2026-03-04 [email protected] Allow stylus support on windows (flutter/flutter#165323)
2026-03-04 [email protected] Fix docs on SingletonFlutterWindow.supportsShowingSystemContextMenu (flutter/flutter#183142)
2026-03-04 [email protected] Roll Packages from 9083bc9 to 82baf93 (5 revisions) (flutter/flutter#183240)
2026-03-04 [email protected] Fixes FocusHighlightMode on Android when typing in software keyboard (flutter/flutter#180753)
2026-03-04 [email protected] Make compileShader() retry without sksl if it fails with sksl. (flutter/flutter#183146)
2026-03-04 [email protected] [web] Use pointer-events: auto for non-interactive leaf semantics nodes (flutter/flutter#183077)

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 [email protected],[email protected] 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:
...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

f: material design flutter/packages/flutter/material repository. framework flutter/packages/flutter repository. See also f: labels.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Proposal: take advantage of relayout parameter in _ScaffoldLayout class constructor

3 participants