Commit b1f9138f authored by Adam Barth's avatar Adam Barth

Switch clients of ScrollableList to ScrollableList2

This patch also changed ScrollableList2 to use an Iterable instead of an
List for its children. This change lets clients map their underlying
data lazily. If the clients actually have a concrete list, we skip the
extra copy and grab the child list directly.
parent 37106ea6
...@@ -14,11 +14,10 @@ class FitnessItemList extends StatelessComponent { ...@@ -14,11 +14,10 @@ class FitnessItemList extends StatelessComponent {
final FitnessItemHandler onDismissed; final FitnessItemHandler onDismissed;
Widget build(BuildContext context) { Widget build(BuildContext context) {
return new ScrollableList<FitnessItem>( return new ScrollableList2(
padding: const EdgeDims.all(4.0), padding: const EdgeDims.all(4.0),
items: items,
itemExtent: kFitnessItemHeight, itemExtent: kFitnessItemHeight,
itemBuilder: (BuildContext context, FitnessItem item, int index) => item.toRow(onDismissed: onDismissed) children: items.map((FitnessItem item) => item.toRow(onDismissed: onDismissed))
); );
} }
} }
......
...@@ -14,10 +14,9 @@ class StockList extends StatelessComponent { ...@@ -14,10 +14,9 @@ class StockList extends StatelessComponent {
final StockRowActionCallback onAction; final StockRowActionCallback onAction;
Widget build(BuildContext context) { Widget build(BuildContext context) {
return new ScrollableList<Stock>( return new ScrollableList2(
items: stocks,
itemExtent: StockRow.kHeight, itemExtent: StockRow.kHeight,
itemBuilder: (BuildContext context, Stock stock, int index) { children: stocks.map((Stock stock) {
return new StockRow( return new StockRow(
keySalt: keySalt, keySalt: keySalt,
stock: stock, stock: stock,
...@@ -25,7 +24,7 @@ class StockList extends StatelessComponent { ...@@ -25,7 +24,7 @@ class StockList extends StatelessComponent {
onDoubleTap: onShow, onDoubleTap: onShow,
onLongPressed: onAction onLongPressed: onAction
); );
} })
); );
} }
} }
...@@ -393,12 +393,11 @@ class CardCollectionState extends State<CardCollection> { ...@@ -393,12 +393,11 @@ class CardCollectionState extends State<CardCollection> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
Widget cardCollection; Widget cardCollection;
if (_fixedSizeCards) { if (_fixedSizeCards) {
cardCollection = new ScrollableList<CardModel> ( cardCollection = new ScrollableList2 (
snapOffsetCallback: _snapToCenter ? _toSnapOffset : null, snapOffsetCallback: _snapToCenter ? _toSnapOffset : null,
snapAlignmentOffset: _cardCollectionSize.height / 2.0, snapAlignmentOffset: _cardCollectionSize.height / 2.0,
items: _cardModels, itemExtent: _cardModels[0].height,
itemBuilder: (BuildContext context, CardModel card, int index) => _buildCard(context, card.value), children: _cardModels.map((CardModel card) => _buildCard(context, card.value))
itemExtent: _cardModels[0].height
); );
} else { } else {
cardCollection = new ScrollableMixedWidgetList( cardCollection = new ScrollableMixedWidgetList(
......
...@@ -74,12 +74,12 @@ class MediaQueryExample extends StatelessComponent { ...@@ -74,12 +74,12 @@ class MediaQueryExample extends StatelessComponent {
if (MediaQuery.of(context).size.width < _gridViewBreakpoint) { if (MediaQuery.of(context).size.width < _gridViewBreakpoint) {
return new ScrollableList2( return new ScrollableList2(
itemExtent: 50.0, itemExtent: 50.0,
children: items.map((AdaptiveItem item) => item.toListItem()).toList() children: items.map((AdaptiveItem item) => item.toListItem())
); );
} else { } else {
return new ScrollableGrid( return new ScrollableGrid(
delegate: new MaxTileWidthGridDelegate(maxTileWidth: _maxTileWidth), delegate: new MaxTileWidthGridDelegate(maxTileWidth: _maxTileWidth),
children: items.map((AdaptiveItem item) => item.toCard()).toList() children: items.map((AdaptiveItem item) => item.toCard())
); );
} }
} }
......
...@@ -5,6 +5,21 @@ ...@@ -5,6 +5,21 @@
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
final NumberFormat _dd = new NumberFormat("00", "en_US");
class _Item extends StatelessComponent {
_Item(this.index);
int index;
Widget build(BuildContext context) {
return new Text('Item ${_dd.format(index)}',
key: new ValueKey<int>(index),
style: Theme.of(context).text.title
);
}
}
class ScrollbarApp extends StatefulComponent { class ScrollbarApp extends StatefulComponent {
ScrollbarAppState createState() => new ScrollbarAppState(); ScrollbarAppState createState() => new ScrollbarAppState();
} }
...@@ -15,17 +30,10 @@ class ScrollbarAppState extends State<ScrollbarApp> { ...@@ -15,17 +30,10 @@ class ScrollbarAppState extends State<ScrollbarApp> {
final ScrollbarPainter _scrollbarPainter = new ScrollbarPainter(); final ScrollbarPainter _scrollbarPainter = new ScrollbarPainter();
Widget _buildMenu(BuildContext context) { Widget _buildMenu(BuildContext context) {
NumberFormat dd = new NumberFormat("00", "en_US"); return new ScrollableList2(
return new ScrollableList<int>(
items: new List<int>.generate(_itemCount, (int i) => i),
itemExtent: _itemExtent, itemExtent: _itemExtent,
itemBuilder: (_, __, int index) { scrollableListPainter: _scrollbarPainter,
return new Text('Item ${dd.format(index)}', children: new List<Widget>.generate(_itemCount, (int i) => new _Item(i))
key: new ValueKey<int>(index),
style: Theme.of(context).text.title
);
},
scrollableListPainter: _scrollbarPainter
); );
} }
......
...@@ -21,44 +21,35 @@ Map<MaterialListType, double> _kItemExtent = const <MaterialListType, double>{ ...@@ -21,44 +21,35 @@ Map<MaterialListType, double> _kItemExtent = const <MaterialListType, double>{
MaterialListType.threeLine: kThreeLineListItemHeight, MaterialListType.threeLine: kThreeLineListItemHeight,
}; };
class MaterialList<T> extends StatefulComponent { class MaterialList extends StatefulComponent {
MaterialList({ MaterialList({
Key key, Key key,
this.initialScrollOffset, this.initialScrollOffset,
this.onScroll, this.onScroll,
this.items, this.type: MaterialListType.twoLine,
this.itemBuilder, this.children
this.type: MaterialListType.twoLine
}) : super(key: key); }) : super(key: key);
final double initialScrollOffset; final double initialScrollOffset;
final ScrollListener onScroll; final ScrollListener onScroll;
final List<T> items;
final ItemBuilder<T> itemBuilder;
final MaterialListType type; final MaterialListType type;
final Iterable<Widget> children;
_MaterialListState<T> createState() => new _MaterialListState<T>(); _MaterialListState createState() => new _MaterialListState();
} }
class _MaterialListState<T> extends State<MaterialList<T>> { class _MaterialListState extends State<MaterialList> {
ScrollbarPainter _scrollbarPainter = new ScrollbarPainter();
void initState() {
super.initState();
_scrollbarPainter = new ScrollbarPainter();
}
ScrollbarPainter _scrollbarPainter;
Widget build(BuildContext context) { Widget build(BuildContext context) {
return new ScrollableList<T>( return new ScrollableList2(
initialScrollOffset: config.initialScrollOffset, initialScrollOffset: config.initialScrollOffset,
scrollDirection: ScrollDirection.vertical, scrollDirection: ScrollDirection.vertical,
onScroll: config.onScroll, onScroll: config.onScroll,
items: config.items,
itemBuilder: config.itemBuilder,
itemExtent: _kItemExtent[config.type], itemExtent: _kItemExtent[config.type],
padding: const EdgeDims.symmetric(vertical: 8.0), padding: const EdgeDims.symmetric(vertical: 8.0),
scrollableListPainter: _scrollbarPainter scrollableListPainter: _scrollbarPainter,
children: config.children
); );
} }
} }
...@@ -36,7 +36,7 @@ typedef double _Constrainer(double value); ...@@ -36,7 +36,7 @@ typedef double _Constrainer(double value);
abstract class RenderBlockBase extends RenderBox abstract class RenderBlockBase extends RenderBox
with ContainerRenderObjectMixin<RenderBox, BlockParentData>, with ContainerRenderObjectMixin<RenderBox, BlockParentData>,
RenderBoxContainerDefaultsMixin<RenderBox, BlockParentData> RenderBoxContainerDefaultsMixin<RenderBox, BlockParentData>
implements RenderScrollable { implements HasScrollDirection {
RenderBlockBase({ RenderBlockBase({
List<RenderBox> children, List<RenderBox> children,
......
...@@ -11,7 +11,7 @@ import 'viewport.dart'; ...@@ -11,7 +11,7 @@ import 'viewport.dart';
/// Parent data for use with [RenderList]. /// Parent data for use with [RenderList].
class ListParentData extends ContainerBoxParentDataMixin<RenderBox> { } class ListParentData extends ContainerBoxParentDataMixin<RenderBox> { }
class RenderList extends RenderVirtualViewport<ListParentData> implements RenderScrollable { class RenderList extends RenderVirtualViewport<ListParentData> implements HasScrollDirection {
RenderList({ RenderList({
List<RenderBox> children, List<RenderBox> children,
double itemExtent, double itemExtent,
......
...@@ -18,7 +18,7 @@ enum ScrollDirection { ...@@ -18,7 +18,7 @@ enum ScrollDirection {
vertical, vertical,
} }
abstract class RenderScrollable { abstract class HasScrollDirection {
ScrollDirection get scrollDirection; ScrollDirection get scrollDirection;
} }
...@@ -32,7 +32,7 @@ abstract class RenderScrollable { ...@@ -32,7 +32,7 @@ abstract class RenderScrollable {
/// Viewport is the core scrolling primitive in the system, but it can be used /// Viewport is the core scrolling primitive in the system, but it can be used
/// in other situations. /// in other situations.
class RenderViewport extends RenderBox with RenderObjectWithChildMixin<RenderBox> class RenderViewport extends RenderBox with RenderObjectWithChildMixin<RenderBox>
implements RenderScrollable { implements HasScrollDirection {
RenderViewport({ RenderViewport({
RenderBox child, RenderBox child,
......
...@@ -446,14 +446,15 @@ class Block extends StatelessComponent { ...@@ -446,14 +446,15 @@ class Block extends StatelessComponent {
abstract class ScrollableListPainter extends Painter { abstract class ScrollableListPainter extends Painter {
void attach(RenderObject renderObject) { void attach(RenderObject renderObject) {
assert(renderObject is RenderBox); assert(renderObject is RenderBox);
assert(renderObject is RenderScrollable); assert(renderObject is HasScrollDirection);
super.attach(renderObject); super.attach(renderObject);
} }
RenderBox get renderObject => super.renderObject; RenderBox get renderObject => super.renderObject;
ScrollDirection get scrollDirection { ScrollDirection get scrollDirection {
return (renderObject as RenderScrollable)?.scrollDirection; HasScrollDirection scrollable = renderObject as dynamic;
return scrollable?.scrollDirection;
} }
Size get viewportSize => renderObject.size; Size get viewportSize => renderObject.size;
......
...@@ -36,7 +36,7 @@ class ScrollableGrid extends Scrollable { ...@@ -36,7 +36,7 @@ class ScrollableGrid extends Scrollable {
); );
final GridDelegate delegate; final GridDelegate delegate;
final List<Widget> children; final Iterable<Widget> children;
ScrollableState createState() => new _ScrollableGridState(); ScrollableState createState() => new _ScrollableGridState();
} }
...@@ -77,7 +77,7 @@ class GridViewport extends VirtualViewport { ...@@ -77,7 +77,7 @@ class GridViewport extends VirtualViewport {
final double startOffset; final double startOffset;
final GridDelegate delegate; final GridDelegate delegate;
final ExtentsChangedCallback onExtentsChanged; final ExtentsChangedCallback onExtentsChanged;
final List<Widget> children; final Iterable<Widget> children;
// TODO(abarth): Support horizontal scrolling; // TODO(abarth): Support horizontal scrolling;
ScrollDirection get scrollDirection => ScrollDirection.vertical; ScrollDirection get scrollDirection => ScrollDirection.vertical;
...@@ -139,8 +139,8 @@ class _GridViewportElement extends VirtualViewportElement<GridViewport> { ...@@ -139,8 +139,8 @@ class _GridViewportElement extends VirtualViewportElement<GridViewport> {
int materializedRowBase = math.max(0, _lowerBound(_specification.rowOffsets, widget.startOffset) - 1); int materializedRowBase = math.max(0, _lowerBound(_specification.rowOffsets, widget.startOffset) - 1);
int materializedRowLimit = math.min(_specification.rowCount, _lowerBound(_specification.rowOffsets, widget.startOffset + containerExtent)); int materializedRowLimit = math.min(_specification.rowCount, _lowerBound(_specification.rowOffsets, widget.startOffset + containerExtent));
_materializedChildBase = (materializedRowBase * _specification.columnCount).clamp(0, widget.children.length); _materializedChildBase = (materializedRowBase * _specification.columnCount).clamp(0, renderObject.virtualChildCount);
_materializedChildCount = (materializedRowLimit * _specification.columnCount).clamp(0, widget.children.length) - _materializedChildBase; _materializedChildCount = (materializedRowLimit * _specification.columnCount).clamp(0, renderObject.virtualChildCount) - _materializedChildBase;
_repaintOffsetBase = _specification.rowOffsets[materializedRowBase]; _repaintOffsetBase = _specification.rowOffsets[materializedRowBase];
_repaintOffsetLimit = _specification.rowOffsets[materializedRowLimit]; _repaintOffsetLimit = _specification.rowOffsets[materializedRowLimit];
......
...@@ -39,7 +39,7 @@ class ScrollableList2 extends Scrollable { ...@@ -39,7 +39,7 @@ class ScrollableList2 extends Scrollable {
final bool itemsWrap; final bool itemsWrap;
final EdgeDims padding; final EdgeDims padding;
final ScrollableListPainter scrollableListPainter; final ScrollableListPainter scrollableListPainter;
final List<Widget> children; final Iterable<Widget> children;
ScrollableState createState() => new _ScrollableList2State(); ScrollableState createState() => new _ScrollableList2State();
} }
...@@ -111,7 +111,7 @@ class ListViewport extends VirtualViewport { ...@@ -111,7 +111,7 @@ class ListViewport extends VirtualViewport {
final bool itemsWrap; final bool itemsWrap;
final EdgeDims padding; final EdgeDims padding;
final Painter overlayPainter; final Painter overlayPainter;
final List<Widget> children; final Iterable<Widget> children;
RenderList createRenderObject() => new RenderList(itemExtent: itemExtent); RenderList createRenderObject() => new RenderList(itemExtent: itemExtent);
...@@ -156,14 +156,14 @@ class _ListViewportElement extends VirtualViewportElement<ListViewport> { ...@@ -156,14 +156,14 @@ class _ListViewportElement extends VirtualViewportElement<ListViewport> {
} }
void layout(BoxConstraints constraints) { void layout(BoxConstraints constraints) {
double contentExtent = widget.itemExtent * widget.children.length; int length = renderObject.virtualChildCount;
double contentExtent = widget.itemExtent * length;
double containerExtent = _getContainerExtentFromRenderObject(); double containerExtent = _getContainerExtentFromRenderObject();
_materializedChildBase = math.max(0, widget.startOffset ~/ widget.itemExtent); _materializedChildBase = math.max(0, widget.startOffset ~/ widget.itemExtent);
int materializedChildLimit = math.max(0, ((widget.startOffset + containerExtent) / widget.itemExtent).ceil()); int materializedChildLimit = math.max(0, ((widget.startOffset + containerExtent) / widget.itemExtent).ceil());
if (!widget.itemsWrap) { if (!widget.itemsWrap) {
int length = widget.children.length;
_materializedChildBase = math.min(length, _materializedChildBase); _materializedChildBase = math.min(length, _materializedChildBase);
materializedChildLimit = math.min(length, materializedChildLimit); materializedChildLimit = math.min(length, materializedChildLimit);
} }
......
...@@ -12,7 +12,7 @@ typedef void ExtentsChangedCallback(double contentExtent, double containerExtent ...@@ -12,7 +12,7 @@ typedef void ExtentsChangedCallback(double contentExtent, double containerExtent
abstract class VirtualViewport extends RenderObjectWidget { abstract class VirtualViewport extends RenderObjectWidget {
double get startOffset; double get startOffset;
ScrollDirection get scrollDirection; ScrollDirection get scrollDirection;
List<Widget> get children; Iterable<Widget> get children;
} }
abstract class VirtualViewportElement<T extends VirtualViewport> extends RenderObjectElement<T> { abstract class VirtualViewportElement<T extends VirtualViewport> extends RenderObjectElement<T> {
...@@ -36,6 +36,8 @@ abstract class VirtualViewportElement<T extends VirtualViewport> extends RenderO ...@@ -36,6 +36,8 @@ abstract class VirtualViewportElement<T extends VirtualViewport> extends RenderO
void mount(Element parent, dynamic newSlot) { void mount(Element parent, dynamic newSlot) {
super.mount(parent, newSlot); super.mount(parent, newSlot);
_iterator = null;
_widgets = <Widget>[];
renderObject.callback = layout; renderObject.callback = layout;
updateRenderObject(); updateRenderObject();
} }
...@@ -46,6 +48,10 @@ abstract class VirtualViewportElement<T extends VirtualViewport> extends RenderO ...@@ -46,6 +48,10 @@ abstract class VirtualViewportElement<T extends VirtualViewport> extends RenderO
} }
void update(T newWidget) { void update(T newWidget) {
if (widget.children != newWidget.children) {
_iterator = null;
_widgets = <Widget>[];
}
super.update(newWidget); super.update(newWidget);
updateRenderObject(); updateRenderObject();
if (!renderObject.needsLayout) if (!renderObject.needsLayout)
...@@ -96,15 +102,37 @@ abstract class VirtualViewportElement<T extends VirtualViewport> extends RenderO ...@@ -96,15 +102,37 @@ abstract class VirtualViewportElement<T extends VirtualViewport> extends RenderO
BuildableElement.lockState(_materializeChildren); BuildableElement.lockState(_materializeChildren);
} }
Iterator<Widget> _iterator;
List<Widget> _widgets;
void _populateWidgets(int limit) {
if (limit <= _widgets.length)
return;
if (widget.children is List<Widget>) {
_widgets = widget.children;
return;
}
_iterator ??= widget.children.iterator;
while (_widgets.length < limit) {
bool moved = _iterator.moveNext();
assert(moved);
Widget current = _iterator.current;
assert(current != null);
_widgets.add(current);
}
}
void _materializeChildren() { void _materializeChildren() {
int base = materializedChildBase; int base = materializedChildBase;
int count = materializedChildCount; int count = materializedChildCount;
int length = renderObject.virtualChildCount;
assert(base != null); assert(base != null);
assert(count != null); assert(count != null);
_populateWidgets(base + count);
List<Widget> newWidgets = new List<Widget>(count); List<Widget> newWidgets = new List<Widget>(count);
for (int i = 0; i < count; ++i) { for (int i = 0; i < count; ++i) {
int childIndex = base + i; int childIndex = base + i;
Widget child = widget.children[childIndex % widget.children.length]; Widget child = _widgets[childIndex % length];
Key key = new ValueKey(child.key ?? childIndex); Key key = new ValueKey(child.key ?? childIndex);
newWidgets[i] = new RepaintBoundary(key: key, child: child); newWidgets[i] = new RepaintBoundary(key: key, child: child);
} }
......
...@@ -21,7 +21,7 @@ void handleOnDismissed(int item) { ...@@ -21,7 +21,7 @@ void handleOnDismissed(int item) {
dismissedItems.add(item); dismissedItems.add(item);
} }
Widget buildDismissableItem(BuildContext context, int item, int index) { Widget buildDismissableItem(int item) {
return new Dismissable( return new Dismissable(
key: new ValueKey<int>(item), key: new ValueKey<int>(item),
direction: dismissDirection, direction: dismissDirection,
...@@ -38,11 +38,12 @@ Widget buildDismissableItem(BuildContext context, int item, int index) { ...@@ -38,11 +38,12 @@ Widget buildDismissableItem(BuildContext context, int item, int index) {
Widget widgetBuilder() { Widget widgetBuilder() {
return new Container( return new Container(
padding: const EdgeDims.all(10.0), padding: const EdgeDims.all(10.0),
child: new ScrollableList<int>( child: new ScrollableList2(
items: <int>[0, 1, 2, 3, 4].where((int i) => !dismissedItems.contains(i)).toList(),
itemBuilder: buildDismissableItem,
scrollDirection: scrollDirection, scrollDirection: scrollDirection,
itemExtent: itemExtent itemExtent: itemExtent,
children: <int>[0, 1, 2, 3, 4].where(
(int i) => !dismissedItems.contains(i)
).map(buildDismissableItem)
) )
); );
} }
......
...@@ -99,16 +99,15 @@ void main() { ...@@ -99,16 +99,15 @@ void main() {
(key.currentState as StateMarkerState).marker = "marked"; (key.currentState as StateMarkerState).marker = "marked";
tester.pumpWidget(new ScrollableList<int>( tester.pumpWidget(new ScrollableList2(
items: <int>[0],
itemExtent: 100.0, itemExtent: 100.0,
itemBuilder: (BuildContext context, int item, int index) { children: <Widget>[
return new Container( new Container(
key: new Key('container'), key: new Key('container'),
height: 100.0, height: 100.0,
child: new StateMarker(key: key) child: new StateMarker(key: key)
); )
} ]
)); ));
expect((key.currentState as StateMarkerState).marker, equals("marked")); expect((key.currentState as StateMarkerState).marker, equals("marked"));
......
...@@ -17,20 +17,18 @@ void main() { ...@@ -17,20 +17,18 @@ void main() {
tester.pumpWidget(new Center( tester.pumpWidget(new Center(
child: new Container( child: new Container(
height: 50.0, height: 50.0,
child: new ScrollableList<int>( child: new ScrollableList2(
key: new GlobalKey(), key: new GlobalKey(),
items: items, itemExtent: 290.0,
itemBuilder: (BuildContext context, int item, int index) { scrollDirection: ScrollDirection.horizontal,
children: items.map((int item) {
return new Container( return new Container(
key: new ValueKey<int>(item),
child: new GestureDetector( child: new GestureDetector(
onTap: () { tapped.add(item); }, onTap: () { tapped.add(item); },
child: new Text('$item') child: new Text('$item')
) )
); );
}, })
itemExtent: 290.0,
scrollDirection: ScrollDirection.horizontal
) )
) )
)); ));
...@@ -59,20 +57,18 @@ void main() { ...@@ -59,20 +57,18 @@ void main() {
tester.pumpWidget(new Center( tester.pumpWidget(new Center(
child: new Container( child: new Container(
width: 50.0, width: 50.0,
child: new ScrollableList<int>( child: new ScrollableList2(
key: new GlobalKey(), key: new GlobalKey(),
items: items, itemExtent: 290.0,
itemBuilder: (BuildContext context, int item, int index) { scrollDirection: ScrollDirection.vertical,
children: items.map((int item) {
return new Container( return new Container(
key: new ValueKey<int>(item),
child: new GestureDetector( child: new GestureDetector(
onTap: () { tapped.add(item); }, onTap: () { tapped.add(item); },
child: new Text('$item') child: new Text('$item')
) )
); );
}, })
itemExtent: 290.0,
scrollDirection: ScrollDirection.vertical
) )
) )
)); ));
......
...@@ -13,16 +13,14 @@ Widget buildFrame() { ...@@ -13,16 +13,14 @@ Widget buildFrame() {
return new Center( return new Center(
child: new Container( child: new Container(
height: 50.0, height: 50.0,
child: new ScrollableList<int>( child: new ScrollableList2(
items: items, itemExtent: 290.0,
itemBuilder: (BuildContext context, int item, int index) { scrollDirection: ScrollDirection.horizontal,
children: items.map((int item) {
return new Container( return new Container(
key: new ValueKey<int>(item),
child: new Text('$item') child: new Text('$item')
); );
}, })
itemExtent: 290.0,
scrollDirection: ScrollDirection.horizontal
) )
) )
); );
......
...@@ -9,16 +9,14 @@ import 'package:test/test.dart'; ...@@ -9,16 +9,14 @@ import 'package:test/test.dart';
const List<int> items = const <int>[0, 1, 2, 3, 4, 5]; const List<int> items = const <int>[0, 1, 2, 3, 4, 5];
Widget buildFrame() { Widget buildFrame() {
return new ScrollableList<int>( return new ScrollableList2(
items: items, itemExtent: 290.0,
itemBuilder: (BuildContext context, int item, int index) { scrollDirection: ScrollDirection.vertical,
children: items.map((int item) {
return new Container( return new Container(
key: new ValueKey<int>(item),
child: new Text('$item') child: new Text('$item')
); );
}, })
itemExtent: 290.0,
scrollDirection: ScrollDirection.vertical
); );
} }
......
...@@ -12,9 +12,8 @@ const double itemExtent = 200.0; ...@@ -12,9 +12,8 @@ const double itemExtent = 200.0;
ScrollDirection scrollDirection = ScrollDirection.vertical; ScrollDirection scrollDirection = ScrollDirection.vertical;
GlobalKey scrollableListKey; GlobalKey scrollableListKey;
Widget buildItem(BuildContext context, int item, int index) { Widget buildItem(int item) {
return new Container( return new Container(
key: new ValueKey<int>(item),
width: itemExtent, width: itemExtent,
height: itemExtent, height: itemExtent,
child: new Text(item.toString()) child: new Text(item.toString())
...@@ -30,13 +29,12 @@ Widget buildFrame() { ...@@ -30,13 +29,12 @@ Widget buildFrame() {
return new Center( return new Center(
child: new Container( child: new Container(
height: itemExtent * 2.0, height: itemExtent * 2.0,
child: new ScrollableList<int>( child: new ScrollableList2(
key: scrollableListKey, key: scrollableListKey,
snapOffsetCallback: snapOffsetCallback, snapOffsetCallback: snapOffsetCallback,
scrollDirection: scrollDirection, scrollDirection: scrollDirection,
items: <int>[0, 1, 2, 3, 4, 5, 7, 8, 9], itemExtent: itemExtent,
itemBuilder: buildItem, children: <int>[0, 1, 2, 3, 4, 5, 7, 8, 9].map(buildItem)
itemExtent: itemExtent
) )
) )
); );
......
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