Commit 2d49e807 authored by Adam Barth's avatar Adam Barth

Remove MixedViewport

Also, port the MixedViewport tests to LazyBlockViewport. Fix bugs found by the tests.
parent 2383d605
......@@ -1241,6 +1241,11 @@ class ErrorWidget extends LeafRenderObjectWidget {
@override
RenderBox createRenderObject(BuildContext context) => new RenderErrorBox(message);
@override
void debugFillDescription(List<String> description) {
description.add('message: ' + _stringify(message));
}
}
/// Base class for instantiations of widgets that have builders and can be
......
......@@ -377,18 +377,8 @@ class _LazyBlockElement extends RenderObjectElement {
renderObject.mainAxis = widget.mainAxis;
LazyBlockDelegate newDelegate = newWidget.delegate;
LazyBlockDelegate oldDelegate = oldWidget.delegate;
if (newDelegate != oldDelegate && (newDelegate.runtimeType != oldDelegate.runtimeType || newDelegate.shouldRebuild(oldDelegate))) {
IndexedBuilder builder = newDelegate.buildItem;
List<Widget> widgets = <Widget>[];
for (int i = 0; i < widgets.length; ++i) {
int logicalIndex = _firstChildLogicalIndex + i;
Widget childWidget = builder(this, logicalIndex);
if (childWidget == null)
break;
widgets[i] = new RepaintBoundary.wrap(childWidget, logicalIndex);
}
_children = new List<Element>.from(updateChildren(_children, widgets));
}
if (newDelegate != oldDelegate && (newDelegate.runtimeType != oldDelegate.runtimeType || newDelegate.shouldRebuild(oldDelegate)))
performRebuild();
// If the new start offset can be displayed properly with the items
// currently represented in _children, we just need to update the paint
// offset. Otherwise, we need to trigger a layout in order to change the
......@@ -405,6 +395,21 @@ class _LazyBlockElement extends RenderObjectElement {
super.unmount();
}
@override
void performRebuild() {
IndexedBuilder builder = widget.delegate.buildItem;
List<Widget> widgets = <Widget>[];
for (int i = 0; i < _children.length; ++i) {
int logicalIndex = _firstChildLogicalIndex + i;
Widget childWidget = builder(this, logicalIndex);
if (childWidget == null)
break;
widgets.add(new RepaintBoundary.wrap(childWidget, logicalIndex));
}
_children = new List<Element>.from(updateChildren(_children, widgets));
super.performRebuild();
}
void _layout(BoxConstraints constraints) {
final double blockExtent = _getMainAxisExtent(renderObject.size);
......
This diff is collapsed.
......@@ -13,7 +13,6 @@ import 'package:flutter/rendering.dart' show HasMainAxis;
import 'basic.dart';
import 'framework.dart';
import 'gesture_detector.dart';
import 'mixed_viewport.dart';
import 'notification_listener.dart';
import 'page_storage.dart';
import 'scroll_behavior.dart';
......@@ -612,11 +611,10 @@ abstract class ScrollableState<T extends Scrollable> extends State<T> {
/// The widgets used by this method should be widgets that provide a
/// layout-time callback that reports the sizes that are relevant to
/// the scroll offset (typically the size of the scrollable
/// container and the scrolled contents). [Viewport] and
/// [MixedViewport] provide an [onPaintOffsetUpdateNeeded] callback
/// for this purpose; [GridViewport], [ListViewport], and
/// [LazyListViewport] provide an [onExtentsChanged] callback for
/// this purpose.
/// container and the scrolled contents). [Viewport] provides an
/// [onPaintOffsetUpdateNeeded] callback for this purpose; [GridViewport],
/// [ListViewport], [LazyListViewport], and [LazyBlockViewport] provide an
/// [onExtentsChanged] callback for this purpose.
///
/// This callback should be used to update the scroll behavior, if
/// necessary, and then to call [updateGestureDetector] to update
......@@ -705,6 +703,10 @@ class _ScrollableViewportState extends ScrollableState<ScrollableViewport> {
/// A mashup of [ScrollableViewport] and [BlockBody]. Useful when you have a small,
/// fixed number of children that you wish to arrange in a block layout and that
/// might exceed the height of its container (and therefore need to scroll).
///
/// If you have a large number of children, consider using [LazyBlock] (if the
/// children have variable height) or [ScrollableList] (if the children all have
/// the same fixed height).
class Block extends StatelessWidget {
Block({
Key key,
......@@ -794,76 +796,3 @@ abstract class ScrollableListPainter extends RenderObjectPainter {
/// or was canceled by the user.
Future<Null> scrollEnded() => new Future<Null>.value();
}
/// A general scrollable list for a large number of children that might not all
/// have the same height. Prefer [ScrollableList] when all the children
/// have the same height because it can use that property to be more efficient.
/// Prefer [ScrollableViewport] with a single child.
///
/// ScrollableMixedWidgetList only supports vertical scrolling.
class ScrollableMixedWidgetList extends Scrollable {
ScrollableMixedWidgetList({
Key key,
double initialScrollOffset,
ScrollListener onScroll,
SnapOffsetCallback snapOffsetCallback,
this.builder,
this.token,
this.onInvalidatorAvailable
}) : super(
key: key,
initialScrollOffset: initialScrollOffset,
onScroll: onScroll,
snapOffsetCallback: snapOffsetCallback
);
// TODO(ianh): Support horizontal scrolling.
final IndexedBuilder builder;
final Object token;
final InvalidatorAvailableCallback onInvalidatorAvailable;
@override
ScrollableMixedWidgetListState createState() => new ScrollableMixedWidgetListState();
}
class ScrollableMixedWidgetListState extends ScrollableState<ScrollableMixedWidgetList> {
@override
void initState() {
super.initState();
scrollBehavior.updateExtents(
contentExtent: double.INFINITY
);
}
@override
OverscrollBehavior createScrollBehavior() => new OverscrollBehavior();
@override
OverscrollBehavior get scrollBehavior => super.scrollBehavior;
Offset _handlePaintOffsetUpdateNeeded(ViewportDimensions dimensions) {
// We make various state changes here but don't have to do so in a
// setState() callback because we are called during layout and all
// we're updating is the new offset, which we are providing to the
// render object via our return value.
didUpdateScrollBehavior(scrollBehavior.updateExtents(
contentExtent: dimensions.contentSize.height,
containerExtent: dimensions.containerSize.height,
scrollOffset: scrollOffset
));
updateGestureDetector();
return scrollOffsetToPixelDelta(scrollOffset);
}
@override
Widget buildContent(BuildContext context) {
return new MixedViewport(
startOffset: scrollOffset,
builder: config.builder,
token: config.token,
onInvalidatorAvailable: config.onInvalidatorAvailable,
onPaintOffsetUpdateNeeded: _handlePaintOffsetUpdateNeeded
);
}
}
......@@ -27,7 +27,6 @@ export 'src/widgets/lazy_block.dart';
export 'src/widgets/locale_query.dart';
export 'src/widgets/media_query.dart';
export 'src/widgets/mimic.dart';
export 'src/widgets/mixed_viewport.dart';
export 'src/widgets/modal_barrier.dart';
export 'src/widgets/navigator.dart';
export 'src/widgets/notification_listener.dart';
......
......@@ -9,7 +9,7 @@ import 'package:test/test.dart';
import 'test_widgets.dart';
void main() {
test('MixedViewport mount/dismount smoke test', () {
test('LazyBlockViewport mount/dismount smoke test', () {
testWidgets((WidgetTester tester) {
List<int> callbackTracker = <int>[];
......@@ -18,15 +18,15 @@ void main() {
Widget builder() {
return new FlipWidget(
left: new MixedViewport(
builder: (BuildContext context, int i) {
left: new LazyBlockViewport(
delegate: new LazyBlockBuilder(builder: (BuildContext context, int i) {
callbackTracker.add(i);
return new Container(
key: new ValueKey<int>(i),
height: 100.0,
child: new Text("$i")
);
},
}),
startOffset: 0.0
),
right: new Text('Not Today')
......@@ -54,7 +54,7 @@ void main() {
});
});
test('MixedViewport vertical', () {
test('LazyBlockViewport vertical', () {
testWidgets((WidgetTester tester) {
List<int> callbackTracker = <int>[];
......@@ -76,8 +76,8 @@ void main() {
Widget builder() {
return new FlipWidget(
left: new MixedViewport(
builder: itemBuilder,
left: new LazyBlockViewport(
delegate: new LazyBlockBuilder(builder: itemBuilder),
startOffset: offset
),
right: new Text('Not Today')
......@@ -86,23 +86,27 @@ void main() {
tester.pumpWidget(builder());
// 0 is built to find its width
// 0 is built to find its height
expect(callbackTracker, equals([0, 1, 2, 3, 4]));
callbackTracker.clear();
offset = 400.0; // now only 3 should fit, numbered 2-4.
tester.pumpWidget(builder());
// 0 and 1 aren't built, we know their size and nothing else changed
expect(callbackTracker, equals([2, 3, 4]));
// We build all the children to find their new size.
expect(callbackTracker, equals([0, 1, 2, 3, 4]));
callbackTracker.clear();
tester.pumpWidget(builder());
// 0 isn't built because they're not visible.
expect(callbackTracker, equals([1, 2, 3, 4]));
callbackTracker.clear();
});
});
test('MixedViewport horizontal', () {
test('LazyBlockViewport horizontal', () {
testWidgets((WidgetTester tester) {
List<int> callbackTracker = <int>[];
......@@ -124,10 +128,10 @@ void main() {
Widget builder() {
return new FlipWidget(
left: new MixedViewport(
builder: itemBuilder,
left: new LazyBlockViewport(
delegate: new LazyBlockBuilder(builder: itemBuilder),
startOffset: offset,
direction: Axis.horizontal
mainAxis: Axis.horizontal
),
right: new Text('Not Today')
);
......@@ -144,14 +148,19 @@ void main() {
tester.pumpWidget(builder());
// 0 and 1 aren't built, we know their size and nothing else changed
expect(callbackTracker, equals([2, 3, 4, 5]));
// We build all the children to find their new size.
expect(callbackTracker, equals([0, 1, 2, 3, 4, 5]));
callbackTracker.clear();
tester.pumpWidget(builder());
// 0 isn't built because they're not visible.
expect(callbackTracker, equals([1, 2, 3, 4, 5]));
callbackTracker.clear();
});
});
test('MixedViewport reinvoke builders', () {
test('LazyBlockViewport reinvoke builders', () {
testWidgets((WidgetTester tester) {
List<int> callbackTracker = <int>[];
List<String> text = <String>[];
......@@ -173,8 +182,8 @@ void main() {
};
Widget builder() {
return new MixedViewport(
builder: itemBuilder,
return new LazyBlockViewport(
delegate: new LazyBlockBuilder(builder: itemBuilder),
startOffset: 0.0
);
}
......@@ -197,7 +206,7 @@ void main() {
});
});
test('MixedViewport reinvoke builders', () {
test('LazyBlockViewport reinvoke builders', () {
testWidgets((WidgetTester tester) {
StateSetter setState;
ThemeData themeData = new ThemeData.light();
......@@ -214,7 +223,9 @@ void main() {
);
};
Widget viewport = new MixedViewport(builder: itemBuilder);
Widget viewport = new LazyBlockViewport(
delegate: new LazyBlockBuilder(builder: itemBuilder)
);
tester.pumpWidget(
new StatefulBuilder(
......
......@@ -28,7 +28,7 @@ Widget buildFrame() {
}
void main() {
test('MixedViewport is a build function (smoketest)', () {
test('LazyBlock is a build function (smoketest)', () {
testWidgets((WidgetTester tester) {
tester.pumpWidget(buildFrame());
expect(tester.findText('0'), isNotNull);
......
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