mirror of
https://github.com/flutter/flutter
synced 2024-10-12 11:12:54 +00:00
Fix scrolling in the Drawer
and NavigationDrawer
triggers AppBar's scrolledUnderElevation (#122600)
Fix scrolling in the `Drawer` and `NavigationDrawer` triggers AppBar's scrolledUnderElevation
This commit is contained in:
parent
32b75f08fe
commit
6e04bddd86
|
@ -763,7 +763,8 @@ class _AppBarState extends State<AppBar> {
|
|||
}
|
||||
|
||||
void _handleScrollNotification(ScrollNotification notification) {
|
||||
if (notification is ScrollUpdateNotification && widget.notificationPredicate(notification)) {
|
||||
if (notification is ScrollUpdateNotification && widget.notificationPredicate(notification)
|
||||
&& Scaffold.isBodyDescendant(notification.context!)) {
|
||||
final bool oldScrolledUnder = _scrolledUnder;
|
||||
final ScrollMetrics metrics = notification.metrics;
|
||||
switch (metrics.axisDirection) {
|
||||
|
|
|
@ -1994,6 +1994,17 @@ class Scaffold extends StatefulWidget {
|
|||
}
|
||||
}
|
||||
|
||||
/// Whether the given context is descendant of the [Scaffold.body].
|
||||
///
|
||||
/// This is used by [AppBar] to determine if the [AppBar] should listen to
|
||||
/// [ScrollNotification] from the [Scrollable]s in the [Scaffold.body].
|
||||
///
|
||||
/// It returns true if the given context is descendant of the [Scaffold.body].
|
||||
static bool isBodyDescendant(BuildContext context) {
|
||||
final _BodyBuilder? body = context.findAncestorWidgetOfExactType<_BodyBuilder>();
|
||||
return body != null;
|
||||
}
|
||||
|
||||
@override
|
||||
ScaffoldState createState() => ScaffoldState();
|
||||
}
|
||||
|
|
|
@ -4501,4 +4501,75 @@ void main() {
|
|||
expect(buttonWasPressed, isFalse);
|
||||
});
|
||||
});
|
||||
|
||||
testWidgets("scrolledUnderElevation only listens to scroll notifications from Scaffold's body", (WidgetTester tester) async {
|
||||
final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();
|
||||
Widget buildWidget() {
|
||||
return MaterialApp(
|
||||
theme: ThemeData(useMaterial3: true),
|
||||
home: Scaffold(
|
||||
key: scaffoldKey,
|
||||
appBar: AppBar(),
|
||||
drawer: Drawer(
|
||||
child: ListView.builder(
|
||||
itemCount: 10,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
return ListTile(
|
||||
title: Text('$index'),
|
||||
);
|
||||
}
|
||||
),
|
||||
),
|
||||
body: ListView.builder(
|
||||
itemCount: 10,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
return ListTile(
|
||||
title: Text('$index'),
|
||||
);
|
||||
}
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
await tester.pumpWidget(buildWidget());
|
||||
|
||||
// The first Material is the AppBar's Material.
|
||||
Material getMaterial() => tester.widget<Material>(find.descendant(
|
||||
of: find.byType(AppBar),
|
||||
matching: find.byType(Material),
|
||||
).first);
|
||||
|
||||
expect(getMaterial().elevation, 0.0);
|
||||
|
||||
// Scroll down the list view in the body.
|
||||
await tester.drag(find.byType(ListView), const Offset(0.0, -300.0));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// AppBar should be elevated.
|
||||
expect(getMaterial().elevation, 3.0);
|
||||
|
||||
// Scroll up the list view in the body.
|
||||
await tester.drag(find.byType(ListView), const Offset(0.0, 300.0));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// AppBar should not be elevated.
|
||||
expect(getMaterial().elevation, 0.0);
|
||||
|
||||
final ScaffoldState state = tester.firstState(find.byType(Scaffold));
|
||||
|
||||
// Open the drawer.
|
||||
state.openDrawer();
|
||||
await tester.pump();
|
||||
await tester.pump(const Duration(seconds: 1));
|
||||
|
||||
expect(scaffoldKey.currentState!.isDrawerOpen, isTrue);
|
||||
|
||||
// Scroll down the list view in the drawer.
|
||||
await tester.drag(find.byType(ListView).last, const Offset(0.0, -250.0));
|
||||
await tester.pump();
|
||||
|
||||
// AppBar should still not be elevated.
|
||||
expect(getMaterial().elevation, 0.0);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -2698,6 +2698,22 @@ void main() {
|
|||
|
||||
expect(tester.takeException(), isNull);
|
||||
});
|
||||
|
||||
testWidgets('Scaffold.isBodyDescendant checks if given context is descendant of the body', (WidgetTester tester) async {
|
||||
final GlobalKey scaffoldKey = GlobalKey();
|
||||
final GlobalKey bodyChildKey = GlobalKey();
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
home: Scaffold(
|
||||
key: scaffoldKey,
|
||||
body: SizedBox(key: bodyChildKey),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
expect(Scaffold.isBodyDescendant(scaffoldKey.currentContext!), false);
|
||||
expect(Scaffold.isBodyDescendant(bodyChildKey.currentContext!), true);
|
||||
});
|
||||
}
|
||||
|
||||
class _GeometryListener extends StatefulWidget {
|
||||
|
|
Loading…
Reference in a new issue