Unverified Commit acf5a259 authored by Kate Lovett's avatar Kate Lovett Committed by GitHub

Add error message when sliver overlap absorber is missing (#128075)

Adds an error message where we previously would crash without any help.
Came across this while working on https://github.com/flutter/flutter/pull/127718
Fixes https://github.com/flutter/flutter/issues/128074
parent f0e32fc6
......@@ -1914,6 +1914,15 @@ class RenderSliverOverlapInjector extends RenderSliver {
void performLayout() {
_currentLayoutExtent = handle.layoutExtent;
_currentMaxExtent = handle.layoutExtent;
assert(
_currentLayoutExtent != null && _currentMaxExtent != null,
'SliverOverlapInjector has found no absorbed extent to inject.\n '
'The SliverOverlapAbsorber must be an earlier descendant of a common '
'ancestor Viewport, so that it will always be laid out before the '
'SliverOverlapInjector during a particular frame.\n '
'The SliverOverlapAbsorber is typically contained in the list of slivers '
'provided by NestedScrollView.headerSliverBuilder.\n'
);
final double clampedLayoutExtent = math.min(
_currentLayoutExtent! - constraints.scrollOffset,
constraints.remainingPaintExtent,
......
......@@ -2908,6 +2908,46 @@ void main() {
// Restructuring inner scrollable while scroll is in progress shouldn't crash.
await tester.pumpWidget(buildApp(nested: true));
});
testWidgets('SliverOverlapInjector asserts when there is no SliverOverlapAbsorber', (WidgetTester tester) async {
Widget buildApp() {
return MaterialApp(
home: Scaffold(
body: NestedScrollView(
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
return <Widget>[
const SliverAppBar(),
];
},
body: Builder(
builder: (BuildContext context) {
return CustomScrollView(
slivers: <Widget>[
SliverOverlapInjector(
handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context),
),
],
);
}
),
),
),
);
}
final List<Object> exceptions = <Object>[];
final FlutterExceptionHandler? oldHandler = FlutterError.onError;
FlutterError.onError = (FlutterErrorDetails details) {
exceptions.add(details.exception);
};
await tester.pumpWidget(buildApp());
FlutterError.onError = oldHandler;
expect(exceptions.length, 4);
expect(exceptions[0], isAssertionError);
expect(
(exceptions[0] as AssertionError).message,
contains('SliverOverlapInjector has found no absorbed extent to inject.'),
);
});
}
double appBarHeight(WidgetTester tester) => tester.getSize(find.byType(AppBar, skipOffstage: false)).height;
......
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