Reland "fix a Scaffold extendBodyBehindAppBar update bug" (#106534)
diff --git a/packages/flutter/lib/src/material/scaffold.dart b/packages/flutter/lib/src/material/scaffold.dart
index 5be81b2..7757cf1 100644
--- a/packages/flutter/lib/src/material/scaffold.dart
+++ b/packages/flutter/lib/src/material/scaffold.dart
@@ -1958,6 +1958,8 @@
final GlobalKey<DrawerControllerState> _drawerKey = GlobalKey<DrawerControllerState>();
final GlobalKey<DrawerControllerState> _endDrawerKey = GlobalKey<DrawerControllerState>();
+ final GlobalKey _bodyKey = GlobalKey();
+
/// Whether this scaffold has a non-null [Scaffold.appBar].
bool get hasAppBar => widget.appBar != null;
/// Whether this scaffold has a non-null [Scaffold.drawer].
@@ -2653,7 +2655,7 @@
widget.body == null ? null : _BodyBuilder(
extendBody: widget.extendBody,
extendBodyBehindAppBar: widget.extendBodyBehindAppBar,
- body: widget.body!,
+ body: KeyedSubtree(key: _bodyKey, child: widget.body!),
),
_ScaffoldSlot.body,
removeLeftPadding: false,
diff --git a/packages/flutter/test/material/scaffold_test.dart b/packages/flutter/test/material/scaffold_test.dart
index b970288..d39ce30 100644
--- a/packages/flutter/test/material/scaffold_test.dart
+++ b/packages/flutter/test/material/scaffold_test.dart
@@ -12,6 +12,39 @@
import '../widgets/semantics_tester.dart';
void main() {
+ // Regression test for https://github.com/flutter/flutter/issues/103741
+ testWidgets('extendBodyBehindAppBar change should not cause the body widget lose state', (WidgetTester tester) async {
+ final ScrollController controller = ScrollController();
+ Widget buildFrame({required bool extendBodyBehindAppBar}) {
+ return MediaQuery(
+ data: const MediaQueryData(),
+ child: Directionality(
+ textDirection: TextDirection.ltr,
+ child: Scaffold(
+ extendBodyBehindAppBar: extendBodyBehindAppBar,
+ resizeToAvoidBottomInset: false,
+ body: SingleChildScrollView(
+ controller: controller,
+ child: const FlutterLogo(
+ size: 1107,
+ ),
+ ),
+ ),
+ ),
+ );
+ }
+
+ await tester.pumpWidget(buildFrame(extendBodyBehindAppBar: true));
+ expect(controller.position.pixels, 0.0);
+
+ controller.jumpTo(100.0);
+ await tester.pump();
+ expect(controller.position.pixels, 100.0);
+
+ await tester.pumpWidget(buildFrame(extendBodyBehindAppBar: false));
+ expect(controller.position.pixels, 100.0);
+ });
+
testWidgets('Scaffold drawer callback test', (WidgetTester tester) async {
bool isDrawerOpen = false;
bool isEndDrawerOpen = false;
@@ -2402,6 +2435,7 @@
' ancestor was:\n'
' Builder\n'
' The ancestors of this widget were:\n'
+ ' KeyedSubtree-[GlobalKey#00000]\n'
' _BodyBuilder\n'
' MediaQuery\n'
' LayoutId-[<_ScaffoldSlot.body>]\n'