mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
Port clients of ScrollableMixedWidgetList to LazyBlock
LazyBlock is going to replace ScrollableMixedWidgetList at some point.
This commit is contained in:
parent
bd407cea0d
commit
40899eb274
@ -44,7 +44,6 @@ class CardCollectionState extends State<CardCollection> {
|
||||
bool _fixedSizeCards = false;
|
||||
bool _sunshine = false;
|
||||
bool _varyFontSizes = false;
|
||||
InvalidatorCallback _invalidator;
|
||||
|
||||
void _initVariableSizedCardModels() {
|
||||
List<double> cardHeights = <double>[
|
||||
@ -304,7 +303,6 @@ class CardCollectionState extends State<CardCollection> {
|
||||
Widget card = new Dismissable(
|
||||
key: new ObjectKey(cardModel),
|
||||
direction: _dismissDirection,
|
||||
onResize: () { if (_invalidator != null) _invalidator(<int>[index]); },
|
||||
onDismissed: (DismissDirection direction) { dismissCard(cardModel); },
|
||||
child: new Card(
|
||||
color: _primaryColor[cardModel.color],
|
||||
@ -413,18 +411,15 @@ class CardCollectionState extends State<CardCollection> {
|
||||
Widget build(BuildContext context) {
|
||||
Widget cardCollection;
|
||||
if (_fixedSizeCards) {
|
||||
_invalidator = null;
|
||||
cardCollection = new ScrollableList(
|
||||
snapOffsetCallback: _snapToCenter ? _toSnapOffset : null,
|
||||
itemExtent: kFixedCardHeight,
|
||||
children: _cardIndices.map/*<Widget>*/((int index) => _buildCard(context, index))
|
||||
);
|
||||
} else {
|
||||
cardCollection = new ScrollableMixedWidgetList(
|
||||
builder: _buildCard,
|
||||
token: _cardModels.length,
|
||||
snapOffsetCallback: _snapToCenter ? _toSnapOffset : null,
|
||||
onInvalidatorAvailable: (InvalidatorCallback callback) { _invalidator = callback; }
|
||||
cardCollection = new LazyBlock(
|
||||
delegate: new LazyBlockBuilder(_buildCard),
|
||||
snapOffsetCallback: _snapToCenter ? _toSnapOffset : null
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -90,11 +90,44 @@ class OverlayGeometryApp extends StatefulWidget {
|
||||
OverlayGeometryAppState createState() => new OverlayGeometryAppState();
|
||||
}
|
||||
|
||||
class OverlayGeometryAppState extends State<OverlayGeometryApp> {
|
||||
typedef void CardTapCallback(Key targetKey, Point globalPosition);
|
||||
|
||||
class CardBuilder extends LazyBlockDelegate {
|
||||
CardBuilder({ this.cardModels, this.onTapUp });
|
||||
|
||||
final List<CardModel> cardModels;
|
||||
final CardTapCallback onTapUp;
|
||||
|
||||
static const TextStyle cardLabelStyle =
|
||||
const TextStyle(color: Colors.white, fontSize: 18.0, fontWeight: FontWeight.bold);
|
||||
|
||||
@override
|
||||
Widget buildItem(BuildContext context, int index) {
|
||||
if (index >= cardModels.length)
|
||||
return null;
|
||||
CardModel cardModel = cardModels[index];
|
||||
return new GestureDetector(
|
||||
key: cardModel.key,
|
||||
onTapUp: (Point globalPosition) { onTapUp(cardModel.targetKey, globalPosition); },
|
||||
child: new Card(
|
||||
key: cardModel.targetKey,
|
||||
color: cardModel.color,
|
||||
child: new Container(
|
||||
height: cardModel.height,
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: new Center(child: new Text(cardModel.label, style: cardLabelStyle))
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
bool shouldRebuild(CardBuilder oldDelegate) {
|
||||
return oldDelegate.cardModels != cardModels;
|
||||
}
|
||||
}
|
||||
|
||||
class OverlayGeometryAppState extends State<OverlayGeometryApp> {
|
||||
List<CardModel> cardModels;
|
||||
Map<MarkerType, Point> markers = new Map<MarkerType, Point>();
|
||||
double markersScrollOffset;
|
||||
@ -125,9 +158,9 @@ class OverlayGeometryAppState extends State<OverlayGeometryApp> {
|
||||
});
|
||||
}
|
||||
|
||||
void handlePointerDown(GlobalKey target, PointerDownEvent event) {
|
||||
void handleTapUp(GlobalKey target, Point globalPosition) {
|
||||
setState(() {
|
||||
markers[MarkerType.touch] = event.position;
|
||||
markers[MarkerType.touch] = globalPosition;
|
||||
final RenderBox box = target.currentContext.findRenderObject();
|
||||
markers[MarkerType.topLeft] = box.localToGlobal(new Point(0.0, 0.0));
|
||||
final Size size = box.size;
|
||||
@ -137,25 +170,6 @@ class OverlayGeometryAppState extends State<OverlayGeometryApp> {
|
||||
});
|
||||
}
|
||||
|
||||
Widget builder(BuildContext context, int index) {
|
||||
if (index >= cardModels.length)
|
||||
return null;
|
||||
CardModel cardModel = cardModels[index];
|
||||
return new Listener(
|
||||
key: cardModel.key,
|
||||
onPointerDown: (PointerDownEvent event) { return handlePointerDown(cardModel.targetKey, event); },
|
||||
child: new Card(
|
||||
key: cardModel.targetKey,
|
||||
color: cardModel.color,
|
||||
child: new Container(
|
||||
height: cardModel.height,
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: new Center(child: new Text(cardModel.label, style: cardLabelStyle))
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
List<Widget> layers = <Widget>[
|
||||
@ -163,10 +177,12 @@ class OverlayGeometryAppState extends State<OverlayGeometryApp> {
|
||||
appBar: new AppBar(title: new Text('Tap a Card')),
|
||||
body: new Container(
|
||||
padding: const EdgeInsets.symmetric(vertical: 12.0, horizontal: 8.0),
|
||||
child: new ScrollableMixedWidgetList(
|
||||
builder: builder,
|
||||
token: cardModels.length,
|
||||
onScroll: handleScroll
|
||||
child: new LazyBlock(
|
||||
onScroll: handleScroll,
|
||||
delegate: new CardBuilder(
|
||||
cardModels: cardModels,
|
||||
onTapUp: handleTapUp
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
@ -33,6 +33,18 @@ abstract class LazyBlockDelegate {
|
||||
bool shouldRebuild(LazyBlockDelegate oldDelegate);
|
||||
}
|
||||
|
||||
class LazyBlockBuilder extends LazyBlockDelegate {
|
||||
LazyBlockBuilder(this.builder);
|
||||
|
||||
final IndexedBuilder builder;
|
||||
|
||||
@override
|
||||
Widget buildItem(BuildContext context, int index) => builder(context, index);
|
||||
|
||||
@override
|
||||
bool shouldRebuild(LazyBlockDelegate oldDelegate) => true;
|
||||
}
|
||||
|
||||
class LazyBlock extends Scrollable {
|
||||
LazyBlock({
|
||||
Key key,
|
||||
@ -124,18 +136,19 @@ class _RenderLazyBlock extends RenderVirtualViewport<_LazyBlockParentData> {
|
||||
child.parentData = new _LazyBlockParentData();
|
||||
}
|
||||
|
||||
double _noIntrinsicExtent() {
|
||||
bool _debugThrowIfNotCheckingIntrinsics() {
|
||||
assert(() {
|
||||
if (!RenderObject.debugCheckingIntrinsics) {
|
||||
throw new UnsupportedError(
|
||||
'MixedViewport does not support returning intrinsic dimensions.\n'
|
||||
'Calculating the intrinsic dimensions would require walking the entire child list,\n'
|
||||
'which defeats the entire point of having a lazily-built list of children.'
|
||||
throw new FlutterError(
|
||||
'LazyBlockViewport does not support returning intrinsic dimensions.\n'
|
||||
'Calculating the intrinsic dimensions would require walking the entire '
|
||||
'child list, which defeats the entire point of having a lazily-built '
|
||||
'list of children.'
|
||||
);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
return null;
|
||||
return true;
|
||||
}
|
||||
|
||||
double getIntrinsicWidth(BoxConstraints constraints) {
|
||||
@ -143,7 +156,8 @@ class _RenderLazyBlock extends RenderVirtualViewport<_LazyBlockParentData> {
|
||||
case Axis.horizontal:
|
||||
return constraints.constrainWidth(0.0);
|
||||
case Axis.vertical:
|
||||
return _noIntrinsicExtent();
|
||||
assert(_debugThrowIfNotCheckingIntrinsics());
|
||||
return constraints.constrainWidth(0.0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -162,9 +176,10 @@ class _RenderLazyBlock extends RenderVirtualViewport<_LazyBlockParentData> {
|
||||
double getIntrinsicHeight(BoxConstraints constraints) {
|
||||
switch (mainAxis) {
|
||||
case Axis.horizontal:
|
||||
return constraints.constrainWidth(0.0);
|
||||
return constraints.constrainHeight(0.0);
|
||||
case Axis.vertical:
|
||||
return _noIntrinsicExtent();
|
||||
assert(_debugThrowIfNotCheckingIntrinsics());
|
||||
return constraints.constrainHeight(0.0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -259,13 +274,19 @@ class _LazyBlockElement extends RenderObjectElement {
|
||||
LazyBlockViewport oldWidget = widget;
|
||||
super.update(newWidget);
|
||||
renderObject.mainAxis = widget.direction;
|
||||
if (newWidget.delegate.runtimeType != oldWidget.delegate.runtimeType ||
|
||||
newWidget.delegate.shouldRebuild(oldWidget.delegate)) {
|
||||
IndexedBuilder builder = widget.delegate.buildItem;
|
||||
List<Widget> widgets = new List<Widget>(_children.length);
|
||||
for (int i = 0; i < widgets.length; ++i)
|
||||
widgets[i] = builder(this, _firstChildLogicalIndex + i);
|
||||
_children = updateChildren(_children, widgets);
|
||||
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 the new start offset can be displayed properly with the items
|
||||
// currently represented in _children, we just need to update the paint
|
||||
@ -316,8 +337,9 @@ class _LazyBlockElement extends RenderObjectElement {
|
||||
|
||||
while (currentLogicalIndex > 0 && currentLogicalOffset > startLogicalOffset) {
|
||||
currentLogicalIndex -= 1;
|
||||
Widget newWidget = new RepaintBoundary.wrap(builder(this, currentLogicalIndex), currentLogicalIndex);
|
||||
Widget newWidget = builder(this, currentLogicalIndex);
|
||||
assert(newWidget != null);
|
||||
newWidget = new RepaintBoundary.wrap(newWidget, currentLogicalIndex);
|
||||
newChildren.add(inflateWidget(newWidget, null));
|
||||
RenderBox child = block.firstChild;
|
||||
assert(child == newChildren.last.renderObject);
|
||||
@ -383,9 +405,10 @@ class _LazyBlockElement extends RenderObjectElement {
|
||||
int physicalIndex = currentLogicalIndex - _firstChildLogicalIndex;
|
||||
if (physicalIndex >= _children.length) {
|
||||
assert(physicalIndex == _children.length);
|
||||
Widget newWidget = new RepaintBoundary.wrap(builder(this, currentLogicalIndex), currentLogicalIndex);
|
||||
Widget newWidget = builder(this, currentLogicalIndex);
|
||||
if (newWidget == null)
|
||||
break;
|
||||
newWidget = new RepaintBoundary.wrap(newWidget, currentLogicalIndex);
|
||||
Element previousChild = _children.isEmpty ? null : _children.last;
|
||||
_children.add(inflateWidget(newWidget, previousChild));
|
||||
}
|
||||
|
@ -21,13 +21,9 @@ Widget buildCard(BuildContext context, int index) {
|
||||
);
|
||||
}
|
||||
|
||||
InvalidatorCallback invalidator;
|
||||
|
||||
Widget buildFrame() {
|
||||
return new ScrollableMixedWidgetList(
|
||||
builder: buildCard,
|
||||
token: items.length,
|
||||
onInvalidatorAvailable: (InvalidatorCallback callback) { invalidator = callback; }
|
||||
return new LazyBlock(
|
||||
delegate: new LazyBlockBuilder(buildCard)
|
||||
);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user