Commit 1b948cbb authored by Ian Hickson's avatar Ian Hickson Committed by GitHub

Rename SliverFill to SliverFillViewport and add SliverFillRemaining (#9194)

parent e355c601
...@@ -50,6 +50,7 @@ export 'src/rendering/rotated_box.dart'; ...@@ -50,6 +50,7 @@ export 'src/rendering/rotated_box.dart';
export 'src/rendering/semantics.dart'; export 'src/rendering/semantics.dart';
export 'src/rendering/shifted_box.dart'; export 'src/rendering/shifted_box.dart';
export 'src/rendering/sliver.dart'; export 'src/rendering/sliver.dart';
export 'src/rendering/sliver_fill.dart';
export 'src/rendering/sliver_fixed_extent_list.dart'; export 'src/rendering/sliver_fixed_extent_list.dart';
export 'src/rendering/sliver_grid.dart'; export 'src/rendering/sliver_grid.dart';
export 'src/rendering/sliver_list.dart'; export 'src/rendering/sliver_list.dart';
......
...@@ -412,7 +412,7 @@ class SliverConstraints extends Constraints { ...@@ -412,7 +412,7 @@ class SliverConstraints extends Constraints {
'scrollOffset: ${scrollOffset.toStringAsFixed(1)}, ' 'scrollOffset: ${scrollOffset.toStringAsFixed(1)}, '
'remainingPaintExtent: ${remainingPaintExtent.toStringAsFixed(1)}, ' + 'remainingPaintExtent: ${remainingPaintExtent.toStringAsFixed(1)}, ' +
(overlap != 0.0 ? 'overlap: ${overlap.toStringAsFixed(1)}, ' : '') + (overlap != 0.0 ? 'overlap: ${overlap.toStringAsFixed(1)}, ' : '') +
'crossAxisExtent: ${crossAxisExtent.toStringAsFixed(1)}' + 'crossAxisExtent: ${crossAxisExtent.toStringAsFixed(1)}, ' +
'viewportMainAxisExtent: ${viewportMainAxisExtent.toStringAsFixed(1)}' + 'viewportMainAxisExtent: ${viewportMainAxisExtent.toStringAsFixed(1)}' +
')'; ')';
} }
...@@ -1218,19 +1218,19 @@ abstract class RenderSliverHelpers implements RenderSliver { ...@@ -1218,19 +1218,19 @@ abstract class RenderSliverHelpers implements RenderSliver {
// ADAPTER FOR RENDER BOXES INSIDE SLIVERS // ADAPTER FOR RENDER BOXES INSIDE SLIVERS
// Transitions from the RenderSliver world to the RenderBox world. // Transitions from the RenderSliver world to the RenderBox world.
/// A [RenderSliver] that contains a single [RenderBox]. /// An abstract class for [RenderSliver]s that contains a single [RenderBox].
///
/// The child will not be laid out if it is not visible.
/// ///
/// See also: /// See also:
/// ///
/// * [RenderSliver], which explains more about the Sliver protocol. /// * [RenderSliver], which explains more about the Sliver protocol.
/// * [RenderBox], which explains more about the Box protocol. /// * [RenderBox], which explains more about the Box protocol.
/// * [RenderViewport], which allows [RenderSliver] objects to be placed inside /// * [RenderSliverToBoxAdapter], which extends this class to size the child
/// a [RenderBox] (the opposite of this class). /// according to its preferred size.
class RenderSliverToBoxAdapter extends RenderSliver with RenderObjectWithChildMixin<RenderBox>, RenderSliverHelpers { /// * [RenderSliverFillRemaining], which extends this class to size the child
/// to fill the remaining space in the viewport.
abstract class RenderSliverSingleBoxAdapter extends RenderSliver with RenderObjectWithChildMixin<RenderBox>, RenderSliverHelpers {
/// Creates a [RenderSliver] that wraps a [RenderBox]. /// Creates a [RenderSliver] that wraps a [RenderBox].
RenderSliverToBoxAdapter({ RenderSliverSingleBoxAdapter({
RenderBox child, RenderBox child,
}) { }) {
this.child = child; this.child = child;
...@@ -1242,34 +1242,7 @@ class RenderSliverToBoxAdapter extends RenderSliver with RenderObjectWithChildMi ...@@ -1242,34 +1242,7 @@ class RenderSliverToBoxAdapter extends RenderSliver with RenderObjectWithChildMi
child.parentData = new SliverPhysicalParentData(); child.parentData = new SliverPhysicalParentData();
} }
@override void setChildParentData(RenderObject child, SliverConstraints constraints, SliverGeometry geometry) {
void performLayout() {
if (child == null) {
geometry = SliverGeometry.zero;
return;
}
child.layout(constraints.asBoxConstraints(), parentUsesSize: true);
double childExtent;
switch (constraints.axis) {
case Axis.horizontal:
childExtent = child.size.width;
break;
case Axis.vertical:
childExtent = child.size.height;
break;
}
assert(childExtent != null);
final double paintedChildSize = calculatePaintOffset(constraints, from: 0.0, to: childExtent);
assert(paintedChildSize.isFinite);
assert(paintedChildSize >= 0.0);
geometry = new SliverGeometry(
scrollExtent: childExtent,
paintExtent: paintedChildSize,
maxPaintExtent: childExtent,
hitTestExtent: paintedChildSize,
hasVisualOverflow: childExtent > constraints.remainingPaintExtent || constraints.scrollOffset > 0.0,
);
final SliverPhysicalParentData childParentData = child.parentData; final SliverPhysicalParentData childParentData = child.parentData;
assert(constraints.axisDirection != null); assert(constraints.axisDirection != null);
assert(constraints.growthDirection != null); assert(constraints.growthDirection != null);
...@@ -1321,3 +1294,52 @@ class RenderSliverToBoxAdapter extends RenderSliver with RenderObjectWithChildMi ...@@ -1321,3 +1294,52 @@ class RenderSliverToBoxAdapter extends RenderSliver with RenderObjectWithChildMi
// TODO(ianh): semantics - shouldn't walk the invisible children // TODO(ianh): semantics - shouldn't walk the invisible children
} }
/// A [RenderSliver] that contains a single [RenderBox].
///
/// The child will not be laid out if it is not visible. It is sized according
/// to the child's preferences in the main axis, and with a tight constraint
/// forcing it to the dimensions of the viewport in the cross axis.
///
/// See also:
///
/// * [RenderSliver], which explains more about the Sliver protocol.
/// * [RenderBox], which explains more about the Box protocol.
/// * [RenderViewport], which allows [RenderSliver] objects to be placed inside
/// a [RenderBox] (the opposite of this class).
class RenderSliverToBoxAdapter extends RenderSliverSingleBoxAdapter {
/// Creates a [RenderSliver] that wraps a [RenderBox].
RenderSliverToBoxAdapter({
RenderBox child,
}) : super(child: child);
@override
void performLayout() {
if (child == null) {
geometry = SliverGeometry.zero;
return;
}
child.layout(constraints.asBoxConstraints(), parentUsesSize: true);
double childExtent;
switch (constraints.axis) {
case Axis.horizontal:
childExtent = child.size.width;
break;
case Axis.vertical:
childExtent = child.size.height;
break;
}
assert(childExtent != null);
final double paintedChildSize = calculatePaintOffset(constraints, from: 0.0, to: childExtent);
assert(paintedChildSize.isFinite);
assert(paintedChildSize >= 0.0);
geometry = new SliverGeometry(
scrollExtent: childExtent,
paintExtent: paintedChildSize,
maxPaintExtent: childExtent,
hitTestExtent: paintedChildSize,
hasVisualOverflow: childExtent > constraints.remainingPaintExtent || constraints.scrollOffset > 0.0,
);
setChildParentData(child, constraints, geometry);
}
}
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:math' as math;
import 'package:flutter/foundation.dart';
import 'box.dart';
import 'sliver.dart';
import 'sliver_fixed_extent_list.dart';
import 'sliver_multi_box_adaptor.dart';
/// A sliver that contains multiple box children that each fill the viewport.
///
/// [RenderSliverFillViewport] places its children in a linear array along the
/// main axis. Each child is sized to fill the viewport, both in the main and
/// cross axis. A [viewportFraction] factor can be provided to size the children
/// to a multiple of the viewport's main axis dimension (typically a fraction
/// less than 1.0).
///
/// See also:
///
/// * [RenderSliverFillRemaining], which sizes the children based on the
/// remaining space rather than the viewport itself.
/// * [RenderSliverFixedExtentList], which has a configurable [itemExtent].
/// * [RenderSliverList], which does not require its children to have the same
/// * /// extent in the main axis.
class RenderSliverFillViewport extends RenderSliverFixedExtentBoxAdaptor {
/// Creates a sliver that contains multiple box children that each fill the
/// viewport.
///
/// The [childManager] argument must not be null.
RenderSliverFillViewport({
@required RenderSliverBoxChildManager childManager,
double viewportFraction: 1.0,
}) : _viewportFraction = viewportFraction, super(childManager: childManager) {
assert(viewportFraction != null);
assert(viewportFraction > 0.0);
}
@override
double get itemExtent => constraints.viewportMainAxisExtent * viewportFraction;
/// The fraction of the viewport that each child should fill in the main axis.
///
/// If this fraction is less than 1.0, more than one child will be visible at
/// once. If this fraction is greater than 1.0, each child will be larger than
/// the viewport in the main axis.
double get viewportFraction => _viewportFraction;
double _viewportFraction;
set viewportFraction(double value) {
assert(value != null);
if (_viewportFraction == value)
return;
_viewportFraction = value;
markNeedsLayout();
}
double get _padding => (1.0 - viewportFraction) * constraints.viewportMainAxisExtent * 0.5;
@override
double indexToLayoutOffset(double itemExtent, int index) {
return _padding + super.indexToLayoutOffset(itemExtent, index);
}
@override
int getMinChildIndexForScrollOffset(double scrollOffset, double itemExtent) {
return super.getMinChildIndexForScrollOffset(math.max(scrollOffset - _padding, 0.0), itemExtent);
}
@override
int getMaxChildIndexForScrollOffset(double scrollOffset, double itemExtent) {
return super.getMaxChildIndexForScrollOffset(math.max(scrollOffset - _padding, 0.0), itemExtent);
}
@override
double estimateMaxScrollOffset(SliverConstraints constraints, {
int firstIndex,
int lastIndex,
double leadingScrollOffset,
double trailingScrollOffset,
}) {
final double padding = _padding;
return childManager.estimateMaxScrollOffset(
constraints,
firstIndex: firstIndex,
lastIndex: lastIndex,
leadingScrollOffset: leadingScrollOffset - padding,
trailingScrollOffset: trailingScrollOffset - padding,
) + padding + padding;
}
}
/// A sliver that contains a single box child that fills the remaining space in
/// the viewport.
///
/// [RenderSliverFillRemaining] sizes its child to fill the viewport in the
/// cross axis and to fill the remaining space in the viewport in the main axis.
///
/// Typically this will be the last sliver in a viewport, since (by definition)
/// there is never any room for anything beyond this sliver.
///
/// See also:
///
/// * [RenderSliverFillViewport], which sizes its children based on the
/// size of the viewport, regardless of what else is in the scroll view.
/// * [RenderSliverList], which shows a list of variable-sized children in a
/// viewport.
class RenderSliverFillRemaining extends RenderSliverSingleBoxAdapter {
/// Creates a [RenderSliver] that wraps a [RenderBox] which is sized to fit
/// the remaining space in the viewport.
RenderSliverFillRemaining({
RenderBox child,
}) : super(child: child);
@override
void performLayout() {
final double size = constraints.remainingPaintExtent - math.min(constraints.overlap, 0.0);
if (child != null)
child.layout(constraints.asBoxConstraints(minExtent: size, maxExtent: size), parentUsesSize: true);
final double paintedChildSize = calculatePaintOffset(constraints, from: 0.0, to: size);
assert(paintedChildSize.isFinite);
assert(paintedChildSize >= 0.0);
geometry = new SliverGeometry(
scrollExtent: constraints.viewportMainAxisExtent,
paintExtent: paintedChildSize,
maxPaintExtent: paintedChildSize,
hasVisualOverflow: size > constraints.remainingPaintExtent || constraints.scrollOffset > 0.0,
);
if (child != null)
setChildParentData(child, constraints, geometry);
}
}
...@@ -28,8 +28,10 @@ import 'sliver_multi_box_adaptor.dart'; ...@@ -28,8 +28,10 @@ import 'sliver_multi_box_adaptor.dart';
/// See also: /// See also:
/// ///
/// * [RenderSliverFixedExtentList], which has a configurable [itemExtent]. /// * [RenderSliverFixedExtentList], which has a configurable [itemExtent].
/// * [RenderSliverFill], which determines the [itemExtent] based on /// * [RenderSliverFillViewport], which determines the [itemExtent] based on
/// [SliverConstraints.viewportMainAxisExtent]. /// [SliverConstraints.viewportMainAxisExtent].
/// * [RenderSliverFillRemaining], which determines the [itemExtent] based on
/// [SliverConstraints.remainingPaintExtent].
/// * [RenderSliverList], which does not require its children to have the same /// * [RenderSliverList], which does not require its children to have the same
/// extent in the main axis. /// extent in the main axis.
abstract class RenderSliverFixedExtentBoxAdaptor extends RenderSliverMultiBoxAdaptor { abstract class RenderSliverFixedExtentBoxAdaptor extends RenderSliverMultiBoxAdaptor {
...@@ -225,10 +227,12 @@ abstract class RenderSliverFixedExtentBoxAdaptor extends RenderSliverMultiBoxAda ...@@ -225,10 +227,12 @@ abstract class RenderSliverFixedExtentBoxAdaptor extends RenderSliverMultiBoxAda
/// ///
/// See also: /// See also:
/// ///
/// * [RenderSliverFill], which determines the [itemExtent] based on
/// [SliverConstraints.viewportMainAxisExtent].
/// * [RenderSliverList], which does not require its children to have the same /// * [RenderSliverList], which does not require its children to have the same
/// extent in the main axis. /// extent in the main axis.
/// * [RenderSliverFillViewport], which determines the [itemExtent] based on
/// [SliverConstraints.viewportMainAxisExtent].
/// * [RenderSliverFillRemaining], which determines the [itemExtent] based on
/// [SliverConstraints.remainingPaintExtent].
class RenderSliverFixedExtentList extends RenderSliverFixedExtentBoxAdaptor { class RenderSliverFixedExtentList extends RenderSliverFixedExtentBoxAdaptor {
/// Creates a sliver that contains multiple box children that have a given /// Creates a sliver that contains multiple box children that have a given
/// extent in the main axis. /// extent in the main axis.
...@@ -250,80 +254,3 @@ class RenderSliverFixedExtentList extends RenderSliverFixedExtentBoxAdaptor { ...@@ -250,80 +254,3 @@ class RenderSliverFixedExtentList extends RenderSliverFixedExtentBoxAdaptor {
markNeedsLayout(); markNeedsLayout();
} }
} }
/// A sliver that contains a multiple box children that each fill the viewport.
///
/// [RenderSliverFill] places its children in a linear array along the main
/// axis. Each child is sized to fill the viewport, both in the main and cross
/// axis.
///
/// See also:
///
/// * [RenderSliverFixedExtentList], which has a configurable [itemExtent].
/// * [RenderSliverList], which does not require its children to have the same
/// extent in the main axis.
class RenderSliverFill extends RenderSliverFixedExtentBoxAdaptor {
/// Creates a sliver that contains a multiple box children that each fill the
/// viewport.
///
/// The [childManager] argument must not be null.
RenderSliverFill({
@required RenderSliverBoxChildManager childManager,
double viewportFraction: 1.0,
}) : _viewportFraction = viewportFraction, super(childManager: childManager) {
assert(viewportFraction != null);
assert(viewportFraction > 0.0);
}
@override
double get itemExtent => constraints.viewportMainAxisExtent * viewportFraction;
/// The fraction of the viewport that each child should fill in the main axis.
///
/// If this fraction is less than 1.0, more than one child will be visible at
/// once. If this fraction is greater than 1.0, each child will be larger than
/// the viewport in the main axis.
double get viewportFraction => _viewportFraction;
double _viewportFraction;
set viewportFraction(double value) {
assert(value != null);
if (_viewportFraction == value)
return;
_viewportFraction = value;
markNeedsLayout();
}
double get _padding => (1.0 - viewportFraction) * constraints.viewportMainAxisExtent * 0.5;
@override
double indexToLayoutOffset(double itemExtent, int index) {
return _padding + super.indexToLayoutOffset(itemExtent, index);
}
@override
int getMinChildIndexForScrollOffset(double scrollOffset, double itemExtent) {
return super.getMinChildIndexForScrollOffset(math.max(scrollOffset - _padding, 0.0), itemExtent);
}
@override
int getMaxChildIndexForScrollOffset(double scrollOffset, double itemExtent) {
return super.getMaxChildIndexForScrollOffset(math.max(scrollOffset - _padding, 0.0), itemExtent);
}
@override
double estimateMaxScrollOffset(SliverConstraints constraints, {
int firstIndex,
int lastIndex,
double leadingScrollOffset,
double trailingScrollOffset,
}) {
final double padding = _padding;
return childManager.estimateMaxScrollOffset(
constraints,
firstIndex: firstIndex,
lastIndex: lastIndex,
leadingScrollOffset: leadingScrollOffset - padding,
trailingScrollOffset: trailingScrollOffset - padding,
) + padding + padding;
}
}
...@@ -426,7 +426,7 @@ class _PageViewState extends State<PageView> { ...@@ -426,7 +426,7 @@ class _PageViewState extends State<PageView> {
axisDirection: axisDirection, axisDirection: axisDirection,
offset: offset, offset: offset,
slivers: <Widget>[ slivers: <Widget>[
new SliverFill( new SliverFillViewport(
viewportFraction: config.controller.viewportFraction, viewportFraction: config.controller.viewportFraction,
delegate: config.childrenDelegate delegate: config.childrenDelegate
), ),
......
...@@ -334,7 +334,7 @@ class SliverList extends SliverMultiBoxAdaptorWidget { ...@@ -334,7 +334,7 @@ class SliverList extends SliverMultiBoxAdaptorWidget {
/// ///
/// See also: /// See also:
/// ///
/// * [SliverFill], which determines the [itemExtent] based on /// * [SliverFillViewport], which determines the [itemExtent] based on
/// [SliverConstraints.viewportMainAxisExtent]. /// [SliverConstraints.viewportMainAxisExtent].
/// * [SliverList], which does not require its children to have the same /// * [SliverList], which does not require its children to have the same
/// extent in the main axis. /// extent in the main axis.
...@@ -416,17 +416,18 @@ class SliverGrid extends SliverMultiBoxAdaptorWidget { ...@@ -416,17 +416,18 @@ class SliverGrid extends SliverMultiBoxAdaptorWidget {
/// A sliver that contains a multiple box children that each fill the viewport. /// A sliver that contains a multiple box children that each fill the viewport.
/// ///
/// [SliverFill] places its children in a linear array along the main axis. Each /// [SliverFillViewport] places its children in a linear array along the main
/// child is sized to fill the viewport, both in the main and cross axis. /// axis. Each child is sized to fill the viewport, both in the main and cross
/// axis.
/// ///
/// See also: /// See also:
/// ///
/// * [SliverFixedExtentList], which has a configurable [itemExtent]. /// * [SliverFixedExtentList], which has a configurable [itemExtent].
/// * [SliverList], which does not require its children to have the same /// * [SliverList], which does not require its children to have the same
/// extent in the main axis. /// extent in the main axis.
class SliverFill extends SliverMultiBoxAdaptorWidget { class SliverFillViewport extends SliverMultiBoxAdaptorWidget {
/// Creates a sliver whose box children that each fill the viewport. /// Creates a sliver whose box children that each fill the viewport.
SliverFill({ SliverFillViewport({
Key key, Key key,
@required SliverChildDelegate delegate, @required SliverChildDelegate delegate,
this.viewportFraction: 1.0, this.viewportFraction: 1.0,
...@@ -443,13 +444,13 @@ class SliverFill extends SliverMultiBoxAdaptorWidget { ...@@ -443,13 +444,13 @@ class SliverFill extends SliverMultiBoxAdaptorWidget {
final double viewportFraction; final double viewportFraction;
@override @override
RenderSliverFill createRenderObject(BuildContext context) { RenderSliverFillViewport createRenderObject(BuildContext context) {
final SliverMultiBoxAdaptorElement element = context; final SliverMultiBoxAdaptorElement element = context;
return new RenderSliverFill(childManager: element, viewportFraction: viewportFraction); return new RenderSliverFillViewport(childManager: element, viewportFraction: viewportFraction);
} }
@override @override
void updateRenderObject(BuildContext context, RenderSliverFill renderObject) { void updateRenderObject(BuildContext context, RenderSliverFillViewport renderObject) {
renderObject.viewportFraction = viewportFraction; renderObject.viewportFraction = viewportFraction;
} }
} }
...@@ -675,3 +676,28 @@ class SliverMultiBoxAdaptorElement extends RenderObjectElement implements Render ...@@ -675,3 +676,28 @@ class SliverMultiBoxAdaptorElement extends RenderObjectElement implements Render
_childElements.values.toList().forEach(visitor); _childElements.values.toList().forEach(visitor);
} }
} }
/// A sliver that contains a single box child that fills the remaining space in
/// the viewport.
///
/// [SliverFillRemaining] sizes its child to fill the viewport in the cross axis
/// and to fill the remaining space in the viewport in the main axis.
///
/// Typically this will be the last sliver in a viewport, since (by definition)
/// there is never any room for anything beyond this sliver.
///
/// See also:
///
/// * [SliverFillViewport], which sizes its children based on the
/// size of the viewport, regardless of what else is in the scroll view.
/// * [SliverList], which shows a list of variable-sized children in a
/// viewport.
class SliverFillRemaining extends SingleChildRenderObjectWidget {
SliverFillRemaining({
Key key,
Widget child,
}) : super(key: key, child: child);
@override
RenderSliverFillRemaining createRenderObject(BuildContext context) => new RenderSliverFillRemaining();
}
...@@ -6,43 +6,54 @@ import 'package:flutter_test/flutter_test.dart'; ...@@ -6,43 +6,54 @@ import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
void main() { void main() {
testWidgets('SliverFillRemaining control test', (WidgetTester tester) async { testWidgets('SliverFillRemaining - no siblings', (WidgetTester tester) async {
final List<Widget> children = new List<Widget>.generate(20, (int i) { final ScrollController controller = new ScrollController();
return new Container(child: new Text('$i'));
});
await tester.pumpWidget( await tester.pumpWidget(
new CustomScrollView( new CustomScrollView(
controller: controller,
slivers: <Widget>[ slivers: <Widget>[
new SliverFill( new SliverFillRemaining(child: new Container()),
delegate: new SliverChildListDelegate(children),
),
], ],
), ),
); );
expect(tester.renderObject<RenderBox>(find.byType(Container)).size.height, equals(600.0));
final RenderBox box = tester.renderObject<RenderBox>(find.byType(Container).first); controller.jumpTo(50.0);
expect(box.size.height, equals(600.0)); await tester.pump();
expect(tester.renderObject<RenderBox>(find.byType(Container)).size.height, equals(600.0));
expect(find.text('0'), findsOneWidget); controller.jumpTo(-100.0);
expect(find.text('1'), findsNothing); await tester.pump();
expect(find.text('2'), findsNothing); expect(tester.renderObject<RenderBox>(find.byType(Container)).size.height, equals(600.0));
await tester.drag(find.byType(Scrollable), const Offset(0.0, -700.0)); controller.jumpTo(0.0);
await tester.pump(); await tester.pump();
expect(tester.renderObject<RenderBox>(find.byType(Container)).size.height, equals(600.0));
});
expect(find.text('0'), findsNothing); testWidgets('SliverFillRemaining - one sibling', (WidgetTester tester) async {
expect(find.text('1'), findsOneWidget); final ScrollController controller = new ScrollController();
expect(find.text('2'), findsOneWidget); await tester.pumpWidget(
expect(find.text('3'), findsNothing); new CustomScrollView(
expect(find.text('4'), findsNothing); controller: controller,
slivers: <Widget>[
new SliverToBoxAdapter(child: new SizedBox(height: 100.0)),
new SliverFillRemaining(child: new Container()),
],
),
);
expect(tester.renderObject<RenderBox>(find.byType(Container)).size.height, equals(500.0));
await tester.drag(find.byType(Scrollable), const Offset(0.0, 200.0)); controller.jumpTo(50.0);
await tester.pump(); await tester.pump();
expect(tester.renderObject<RenderBox>(find.byType(Container)).size.height, equals(550.0));
expect(find.text('0'), findsOneWidget); controller.jumpTo(-100.0);
expect(find.text('1'), findsOneWidget); await tester.pump();
expect(find.text('2'), findsNothing); expect(tester.renderObject<RenderBox>(find.byType(Container)).size.height, equals(400.0)); // (!)
expect(find.text('3'), findsNothing);
controller.jumpTo(0.0);
await tester.pump();
expect(tester.renderObject<RenderBox>(find.byType(Container)).size.height, equals(500.0));
}); });
} }
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/widgets.dart';
void main() {
testWidgets('SliverFillRemaining control test', (WidgetTester tester) async {
final List<Widget> children = new List<Widget>.generate(20, (int i) {
return new Container(child: new Text('$i'));
});
await tester.pumpWidget(
new CustomScrollView(
slivers: <Widget>[
new SliverFillViewport(
delegate: new SliverChildListDelegate(children),
),
],
),
);
final RenderBox box = tester.renderObject<RenderBox>(find.byType(Container).first);
expect(box.size.height, equals(600.0));
expect(find.text('0'), findsOneWidget);
expect(find.text('1'), findsNothing);
expect(find.text('2'), findsNothing);
await tester.drag(find.byType(Scrollable), const Offset(0.0, -700.0));
await tester.pump();
expect(find.text('0'), findsNothing);
expect(find.text('1'), findsOneWidget);
expect(find.text('2'), findsOneWidget);
expect(find.text('3'), findsNothing);
expect(find.text('4'), findsNothing);
await tester.drag(find.byType(Scrollable), const Offset(0.0, 200.0));
await tester.pump();
expect(find.text('0'), findsOneWidget);
expect(find.text('1'), findsOneWidget);
expect(find.text('2'), findsNothing);
expect(find.text('3'), findsNothing);
await tester.drag(find.byType(Scrollable), const Offset(0.0, 700.0));
await tester.pump();
final RenderBox box2 = tester.renderObject<RenderBox>(find.byType(Container).first);
expect(box2.size.height, equals(600.0));
expect(find.text('0'), findsOneWidget);
expect(find.text('1'), findsNothing);
expect(find.text('2'), findsNothing);
expect(find.text('3'), findsNothing);
});
}
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