Skip to content

Commit acf5a25

Browse files
authored
Add error message when sliver overlap absorber is missing (flutter#128075)
Adds an error message where we previously would crash without any help. Came across this while working on flutter#127718 Fixes flutter#128074
1 parent f0e32fc commit acf5a25

File tree

2 files changed

+49
-0
lines changed

2 files changed

+49
-0
lines changed

packages/flutter/lib/src/widgets/nested_scroll_view.dart

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1914,6 +1914,15 @@ class RenderSliverOverlapInjector extends RenderSliver {
19141914
void performLayout() {
19151915
_currentLayoutExtent = handle.layoutExtent;
19161916
_currentMaxExtent = handle.layoutExtent;
1917+
assert(
1918+
_currentLayoutExtent != null && _currentMaxExtent != null,
1919+
'SliverOverlapInjector has found no absorbed extent to inject.\n '
1920+
'The SliverOverlapAbsorber must be an earlier descendant of a common '
1921+
'ancestor Viewport, so that it will always be laid out before the '
1922+
'SliverOverlapInjector during a particular frame.\n '
1923+
'The SliverOverlapAbsorber is typically contained in the list of slivers '
1924+
'provided by NestedScrollView.headerSliverBuilder.\n'
1925+
);
19171926
final double clampedLayoutExtent = math.min(
19181927
_currentLayoutExtent! - constraints.scrollOffset,
19191928
constraints.remainingPaintExtent,

packages/flutter/test/widgets/nested_scroll_view_test.dart

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2908,6 +2908,46 @@ void main() {
29082908
// Restructuring inner scrollable while scroll is in progress shouldn't crash.
29092909
await tester.pumpWidget(buildApp(nested: true));
29102910
});
2911+
2912+
testWidgets('SliverOverlapInjector asserts when there is no SliverOverlapAbsorber', (WidgetTester tester) async {
2913+
Widget buildApp() {
2914+
return MaterialApp(
2915+
home: Scaffold(
2916+
body: NestedScrollView(
2917+
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
2918+
return <Widget>[
2919+
const SliverAppBar(),
2920+
];
2921+
},
2922+
body: Builder(
2923+
builder: (BuildContext context) {
2924+
return CustomScrollView(
2925+
slivers: <Widget>[
2926+
SliverOverlapInjector(
2927+
handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context),
2928+
),
2929+
],
2930+
);
2931+
}
2932+
),
2933+
),
2934+
),
2935+
);
2936+
}
2937+
final List<Object> exceptions = <Object>[];
2938+
final FlutterExceptionHandler? oldHandler = FlutterError.onError;
2939+
FlutterError.onError = (FlutterErrorDetails details) {
2940+
exceptions.add(details.exception);
2941+
};
2942+
await tester.pumpWidget(buildApp());
2943+
FlutterError.onError = oldHandler;
2944+
expect(exceptions.length, 4);
2945+
expect(exceptions[0], isAssertionError);
2946+
expect(
2947+
(exceptions[0] as AssertionError).message,
2948+
contains('SliverOverlapInjector has found no absorbed extent to inject.'),
2949+
);
2950+
});
29112951
}
29122952

29132953
double appBarHeight(WidgetTester tester) => tester.getSize(find.byType(AppBar, skipOffstage: false)).height;

0 commit comments

Comments
 (0)