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
This commit is contained in:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user