Unverified Commit 81bbd3e1 authored by Kate Lovett's avatar Kate Lovett Committed by GitHub

SliverFillRemaining flag for different use cases (#33627)

* WIP

* Fixing nested scroll view tests

* Fixing nested scroll view tests

* Fixing nested scroll view tests

* WIP

* Added flag for SliverFillRemaining

* Clean up

* Review

* Reverted nested scroll view tests

* Updating tests

* Updated for overscroll behavior
parent ef1e6412
......@@ -113,18 +113,35 @@ class RenderSliverFillRemaining extends RenderSliverSingleBoxAdapter {
/// the remaining space in the viewport.
RenderSliverFillRemaining({
RenderBox child,
}) : super(child: child);
this.hasScrollBody = true,
}) : assert(hasScrollBody != null),
super(child: child);
/// Whether the child has a scrollable body, this value cannot be null.
///
/// Defaults to true such that the child will extend beyond the viewport and
/// scroll, as seen in [NestedScrollView].
///
/// Setting this value to false will allow the child to fill the remainder of
/// the viewport and not extend further.
bool hasScrollBody;
@override
void performLayout() {
final double extent = constraints.remainingPaintExtent - math.min(constraints.overlap, 0.0);
final double extent = constraints.remainingPaintExtent
- math.min(constraints.overlap, 0.0)
// Adding the offset for when this SliverFillRemaining is not scrollable,
// so it will stretch to fill on overscroll.
+ (hasScrollBody ? 0.0 : constraints.scrollOffset);
if (child != null)
child.layout(constraints.asBoxConstraints(minExtent: extent, maxExtent: extent), parentUsesSize: true);
final double paintedChildSize = calculatePaintOffset(constraints, from: 0.0, to: extent);
assert(paintedChildSize.isFinite);
assert(paintedChildSize >= 0.0);
geometry = SliverGeometry(
scrollExtent: constraints.viewportMainAxisExtent,
// 0.0 can be applied here for cases when there is not scroll body since
// SliverFillRemaining will not have any slivers following it.
scrollExtent: hasScrollBody ? constraints.viewportMainAxisExtent : 0.0,
paintExtent: paintedChildSize,
maxPaintExtent: paintedChildSize,
hasVisualOverflow: extent > constraints.remainingPaintExtent || constraints.scrollOffset > 0.0,
......
......@@ -1368,10 +1368,24 @@ class SliverFillRemaining extends SingleChildRenderObjectWidget {
const SliverFillRemaining({
Key key,
Widget child,
}) : super(key: key, child: child);
this.hasScrollBody = true,
}) : assert(hasScrollBody != null),
super(key: key, child: child);
/// Whether the child has a scrollable body, this value cannot be null.
///
/// Defaults to true such that the child will extend beyond the viewport and
/// scroll, as seen in [NestedScrollView].
///
/// Setting this value to false will allow the child to fill the remainder of
/// the viewport and not extend further.
final bool hasScrollBody;
@override
RenderSliverFillRemaining createRenderObject(BuildContext context) => RenderSliverFillRemaining(hasScrollBody: hasScrollBody);
@override
RenderSliverFillRemaining createRenderObject(BuildContext context) => RenderSliverFillRemaining();
void updateRenderObject(BuildContext context, RenderSliverFillRemaining renderObject) => renderObject.hasScrollBody = hasScrollBody;
}
/// Mark a child as needing to stay alive even when it's in a lazy list that
......
......@@ -3,6 +3,7 @@
// found in the LICENSE file.
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
void main() {
......@@ -62,4 +63,63 @@ void main() {
await tester.pump();
expect(tester.renderObject<RenderBox>(find.byType(Container)).size.height, equals(500.0));
});
testWidgets('SliverFillRemaining does not extend past viewport.', (WidgetTester tester) async {
final ScrollController controller = ScrollController();
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: CustomScrollView(
controller: controller,
slivers: <Widget>[
SliverToBoxAdapter(
child: Container(
color: Colors.red,
height: 150.0,
),
),
SliverFillRemaining(
child: Container(color: Colors.white),
hasScrollBody: false,
),
],
),
),
);
expect(controller.offset, 0.0);
expect(find.byType(Container), findsNWidgets(2));
controller.jumpTo(150.0);
await tester.pumpAndSettle();
expect(controller.offset, 0.0);
expect(find.byType(Container), findsNWidgets(2));
});
testWidgets('SliverFillRemaining scrolls beyond viewport by default.', (WidgetTester tester) async {
final ScrollController controller = ScrollController();
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: CustomScrollView(
controller: controller,
slivers: <Widget>[
SliverToBoxAdapter(
child: Container(
color: Colors.red,
height: 150.0,
),
),
SliverFillRemaining(
child: Container(color: Colors.white),
),
],
),
),
);
expect(controller.offset, 0.0);
expect(find.byType(Container), findsNWidgets(2));
controller.jumpTo(150.0);
await tester.pumpAndSettle();
expect(controller.offset, 150.0);
expect(find.byType(Container), findsOneWidget);
});
}
......@@ -6,7 +6,7 @@ import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/widgets.dart';
void main() {
testWidgets('SliverFillRemaining control test', (WidgetTester tester) async {
testWidgets('SliverFillViewport control test', (WidgetTester tester) async {
final List<Widget> children = List<Widget>.generate(20, (int i) {
return Container(child: Text('$i', textDirection: TextDirection.ltr));
});
......
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