Unverified Commit 32157e3f authored by Taha Tesser's avatar Taha Tesser Committed by GitHub

`AppBar`: Fix nested scroll view doesn't update `AppBar` elevation for Material 3 (#103899)

parent 64cba0e4
...@@ -162,6 +162,7 @@ class AppBar extends StatefulWidget implements PreferredSizeWidget { ...@@ -162,6 +162,7 @@ class AppBar extends StatefulWidget implements PreferredSizeWidget {
this.bottom, this.bottom,
this.elevation, this.elevation,
this.scrolledUnderElevation, this.scrolledUnderElevation,
this.notificationPredicate = defaultScrollNotificationPredicate,
this.shadowColor, this.shadowColor,
this.surfaceTintColor, this.surfaceTintColor,
this.shape, this.shape,
...@@ -197,6 +198,7 @@ class AppBar extends StatefulWidget implements PreferredSizeWidget { ...@@ -197,6 +198,7 @@ class AppBar extends StatefulWidget implements PreferredSizeWidget {
this.systemOverlayStyle, this.systemOverlayStyle,
}) : assert(automaticallyImplyLeading != null), }) : assert(automaticallyImplyLeading != null),
assert(elevation == null || elevation >= 0.0), assert(elevation == null || elevation >= 0.0),
assert(notificationPredicate != null),
assert(primary != null), assert(primary != null),
assert(toolbarOpacity != null), assert(toolbarOpacity != null),
assert(bottomOpacity != null), assert(bottomOpacity != null),
...@@ -421,6 +423,13 @@ class AppBar extends StatefulWidget implements PreferredSizeWidget { ...@@ -421,6 +423,13 @@ class AppBar extends StatefulWidget implements PreferredSizeWidget {
/// shadow. /// shadow.
final double? scrolledUnderElevation; final double? scrolledUnderElevation;
/// A check that specifies which child's [ScrollNotification]s should be
/// listened to.
///
/// By default, checks whether `notification.depth == 0`. Set it to something
/// else for more complicated layouts.
final ScrollNotificationPredicate notificationPredicate;
/// {@template flutter.material.appbar.shadowColor} /// {@template flutter.material.appbar.shadowColor}
/// The color of the shadow below the app bar. /// The color of the shadow below the app bar.
/// ///
...@@ -809,7 +818,7 @@ class _AppBarState extends State<AppBar> { ...@@ -809,7 +818,7 @@ class _AppBarState extends State<AppBar> {
} }
void _handleScrollNotification(ScrollNotification notification) { void _handleScrollNotification(ScrollNotification notification) {
if (notification is ScrollUpdateNotification && notification.depth == 0) { if (notification is ScrollUpdateNotification && widget.notificationPredicate(notification)) {
final bool oldScrolledUnder = _scrolledUnder; final bool oldScrolledUnder = _scrolledUnder;
final ScrollMetrics metrics = notification.metrics; final ScrollMetrics metrics = notification.metrics;
switch (metrics.axisDirection) { switch (metrics.axisDirection) {
......
...@@ -1011,6 +1011,53 @@ void main() { ...@@ -1011,6 +1011,53 @@ void main() {
expect(getMaterial().elevation, 10); expect(getMaterial().elevation, 10);
}); });
testWidgets('scrolledUnderElevation with nested scroll view', (WidgetTester tester) async {
Widget buildAppBar({double? scrolledUnderElevation}) {
return MaterialApp(
theme: ThemeData(useMaterial3: true),
home: Scaffold(
appBar: AppBar(
title: const Text('Title'),
scrolledUnderElevation: scrolledUnderElevation,
notificationPredicate: (ScrollNotification notification) {
return notification.depth == 1;
},
),
body: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: 4,
itemBuilder: (BuildContext context, int index) {
return SizedBox(
height: 600.0,
width: 800.0,
child: ListView.builder(
itemCount: 100,
itemBuilder: (BuildContext context, int index) =>
ListTile(title: Text('Item $index')),
),
);
},
),
),
);
}
Material getMaterial() => tester.widget<Material>(find.descendant(
of: find.byType(AppBar),
matching: find.byType(Material),
));
await tester.pumpWidget(buildAppBar(scrolledUnderElevation: 10));
// Starts with the base elevation.
expect(getMaterial().elevation, 0.0);
await tester.fling(find.text('Item 2'), const Offset(0.0, -600.0), 2000.0);
await tester.pumpAndSettle();
// After scrolling it should be the scrolledUnderElevation.
expect(getMaterial().elevation, 10);
});
group('SliverAppBar elevation', () { group('SliverAppBar elevation', () {
Widget buildSliverAppBar(bool forceElevated, {double? elevation, double? themeElevation}) { Widget buildSliverAppBar(bool forceElevated, {double? elevation, double? themeElevation}) {
return MaterialApp( return MaterialApp(
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment