Commit fe0b9093 authored by Adam Barth's avatar Adam Barth Committed by GitHub

Remove more clients of LazyBlock (#8071)

The last remaining client is complex_layout.
parent 073843f2
...@@ -7,7 +7,7 @@ import 'package:flutter/rendering.dart' show debugDumpRenderTree; ...@@ -7,7 +7,7 @@ import 'package:flutter/rendering.dart' show debugDumpRenderTree;
class CardModel { class CardModel {
CardModel(this.value, this.height) { CardModel(this.value, this.height) {
inputValue = new InputValue(text: "Item $value"); inputValue = new InputValue(text: 'Item $value');
} }
int value; int value;
double height; double height;
...@@ -37,7 +37,6 @@ class CardCollectionState extends State<CardCollection> { ...@@ -37,7 +37,6 @@ class CardCollectionState extends State<CardCollection> {
DismissDirection _dismissDirection = DismissDirection.horizontal; DismissDirection _dismissDirection = DismissDirection.horizontal;
TextAlign _textAlign = TextAlign.center; TextAlign _textAlign = TextAlign.center;
bool _editable = false; bool _editable = false;
bool _snapToCenter = false;
bool _fixedSizeCards = false; bool _fixedSizeCards = false;
bool _sunshine = false; bool _sunshine = false;
bool _varyFontSizes = false; bool _varyFontSizes = false;
...@@ -46,7 +45,7 @@ class CardCollectionState extends State<CardCollection> { ...@@ -46,7 +45,7 @@ class CardCollectionState extends State<CardCollection> {
List<double> cardHeights = <double>[ List<double> cardHeights = <double>[
48.0, 63.0, 82.0, 146.0, 60.0, 55.0, 84.0, 96.0, 50.0, 48.0, 63.0, 82.0, 146.0, 60.0, 55.0, 84.0, 96.0, 50.0,
48.0, 63.0, 82.0, 146.0, 60.0, 55.0, 84.0, 96.0, 50.0, 48.0, 63.0, 82.0, 146.0, 60.0, 55.0, 84.0, 96.0, 50.0,
48.0, 63.0, 82.0, 146.0, 60.0, 55.0, 84.0, 96.0, 50.0 48.0, 63.0, 82.0, 146.0, 60.0, 55.0, 84.0, 96.0, 50.0,
]; ];
_cardModels = new List<CardModel>.generate( _cardModels = new List<CardModel>.generate(
cardHeights.length, cardHeights.length,
...@@ -58,7 +57,7 @@ class CardCollectionState extends State<CardCollection> { ...@@ -58,7 +57,7 @@ class CardCollectionState extends State<CardCollection> {
const int cardCount = 27; const int cardCount = 27;
_cardModels = new List<CardModel>.generate( _cardModels = new List<CardModel>.generate(
cardCount, cardCount,
(int i) => new CardModel(i, kFixedCardHeight) (int i) => new CardModel(i, kFixedCardHeight),
); );
} }
...@@ -69,48 +68,12 @@ class CardCollectionState extends State<CardCollection> { ...@@ -69,48 +68,12 @@ class CardCollectionState extends State<CardCollection> {
_initVariableSizedCardModels(); _initVariableSizedCardModels();
} }
Iterable<int> get _cardIndices sync* {
for (int i = 0; i < _cardModels.length; i += 1)
yield i;
}
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_initCardModels(); _initCardModels();
} }
double _variableSizeToSnapOffset(double scrollOffset) {
double cumulativeHeight = 0.0;
List<double> cumulativeHeights = _cardModels.map((CardModel card) {
cumulativeHeight += card.height + kCardMargins;
return cumulativeHeight;
})
.toList();
double offsetForIndex(int i) {
return (kCardMargins + _cardModels[i].height) / 2.0 + ((i == 0) ? 0.0 : cumulativeHeights[i - 1]);
}
for (int i = 0; i < cumulativeHeights.length; i++) {
if (cumulativeHeights[i] >= scrollOffset)
return offsetForIndex(i);
}
return offsetForIndex(cumulativeHeights.length - 1);
}
double _fixedSizeToSnapOffset(double scrollOffset) {
int cardIndex = (scrollOffset.clamp(0.0, kFixedCardHeight * (_cardModels.length - 1)) / kFixedCardHeight).floor();
return cardIndex * kFixedCardHeight + kFixedCardHeight * 0.5;
}
double _toSnapOffset(double scrollOffset, Size containerSize) {
double halfHeight = containerSize.height / 2.0;
scrollOffset += halfHeight;
double result = _fixedSizeCards ? _fixedSizeToSnapOffset(scrollOffset) : _variableSizeToSnapOffset(scrollOffset);
return result - halfHeight;
}
void dismissCard(CardModel card) { void dismissCard(CardModel card) {
if (_cardModels.contains(card)) { if (_cardModels.contains(card)) {
setState(() { setState(() {
...@@ -127,7 +90,6 @@ class CardCollectionState extends State<CardCollection> { ...@@ -127,7 +90,6 @@ class CardCollectionState extends State<CardCollection> {
children: <Widget>[ children: <Widget>[
new DrawerHeader(child: new Center(child: new Text('Options'))), new DrawerHeader(child: new Center(child: new Text('Options'))),
buildDrawerCheckbox("Make card labels editable", _editable, _toggleEditable), buildDrawerCheckbox("Make card labels editable", _editable, _toggleEditable),
buildDrawerCheckbox("Snap fling scrolls to center", _snapToCenter, _toggleSnapToCenter),
buildDrawerCheckbox("Fixed size cards", _fixedSizeCards, _toggleFixedSizeCards), buildDrawerCheckbox("Fixed size cards", _fixedSizeCards, _toggleFixedSizeCards),
buildDrawerCheckbox("Let the sun shine", _sunshine, _toggleSunshine), buildDrawerCheckbox("Let the sun shine", _sunshine, _toggleSunshine),
buildDrawerCheckbox("Vary font sizes", _varyFontSizes, _toggleVaryFontSizes, enabled: !_editable), buildDrawerCheckbox("Vary font sizes", _varyFontSizes, _toggleVaryFontSizes, enabled: !_editable),
...@@ -148,11 +110,11 @@ class CardCollectionState extends State<CardCollection> { ...@@ -148,11 +110,11 @@ class CardCollectionState extends State<CardCollection> {
new DrawerItem( new DrawerItem(
icon: new Icon(Icons.dvr), icon: new Icon(Icons.dvr),
onPressed: () { debugDumpApp(); debugDumpRenderTree(); }, onPressed: () { debugDumpApp(); debugDumpRenderTree(); },
child: new Text('Dump App to Console') child: new Text('Dump App to Console'),
), ),
] ],
) ),
) ),
); );
} }
...@@ -174,12 +136,6 @@ class CardCollectionState extends State<CardCollection> { ...@@ -174,12 +136,6 @@ class CardCollectionState extends State<CardCollection> {
}); });
} }
void _toggleSnapToCenter() {
setState(() {
_snapToCenter = !_snapToCenter;
});
}
void _toggleSunshine() { void _toggleSunshine() {
setState(() { setState(() {
_sunshine = !_sunshine; _sunshine = !_sunshine;
...@@ -218,10 +174,10 @@ class CardCollectionState extends State<CardCollection> { ...@@ -218,10 +174,10 @@ class CardCollectionState extends State<CardCollection> {
new Expanded(child: new Text(label)), new Expanded(child: new Text(label)),
new Checkbox( new Checkbox(
value: value, value: value,
onChanged: enabled ? (_) { callback(); } : null onChanged: enabled ? (_) { callback(); } : null,
) ),
] ],
) ),
); );
} }
...@@ -235,10 +191,10 @@ class CardCollectionState extends State<CardCollection> { ...@@ -235,10 +191,10 @@ class CardCollectionState extends State<CardCollection> {
new Radio<Map<int, Color>>( new Radio<Map<int, Color>>(
value: itemValue, value: itemValue,
groupValue: currentValue, groupValue: currentValue,
onChanged: enabled ? onChanged : null onChanged: enabled ? onChanged : null,
) ),
] ],
) ),
); );
} }
...@@ -252,10 +208,10 @@ class CardCollectionState extends State<CardCollection> { ...@@ -252,10 +208,10 @@ class CardCollectionState extends State<CardCollection> {
new Radio<DismissDirection>( new Radio<DismissDirection>(
value: itemValue, value: itemValue,
groupValue: currentValue, groupValue: currentValue,
onChanged: enabled ? onChanged : null onChanged: enabled ? onChanged : null,
) ),
] ],
) ),
); );
} }
...@@ -269,10 +225,10 @@ class CardCollectionState extends State<CardCollection> { ...@@ -269,10 +225,10 @@ class CardCollectionState extends State<CardCollection> {
new Radio<TextAlign>( new Radio<TextAlign>(
value: itemValue, value: itemValue,
groupValue: currentValue, groupValue: currentValue,
onChanged: enabled ? onChanged : null onChanged: enabled ? onChanged : null,
) ),
] ],
) ),
); );
} }
...@@ -285,15 +241,12 @@ class CardCollectionState extends State<CardCollection> { ...@@ -285,15 +241,12 @@ class CardCollectionState extends State<CardCollection> {
padding: const EdgeInsets.only(left: 72.0), padding: const EdgeInsets.only(left: 72.0),
height: 128.0, height: 128.0,
alignment: const FractionalOffset(0.0, 0.75), alignment: const FractionalOffset(0.0, 0.75),
child: new Text('Swipe Away: ${_cardModels.length}', style: Theme.of(context).primaryTextTheme.title) child: new Text('Swipe Away: ${_cardModels.length}', style: Theme.of(context).primaryTextTheme.title),
) ),
); );
} }
Widget _buildCard(BuildContext context, int index) { Widget _buildCard(BuildContext context, int index) {
if (index >= _cardModels.length)
return null;
CardModel cardModel = _cardModels[index]; CardModel cardModel = _cardModels[index];
Widget card = new Dismissable( Widget card = new Dismissable(
key: new ObjectKey(cardModel), key: new ObjectKey(cardModel),
...@@ -312,8 +265,8 @@ class CardCollectionState extends State<CardCollection> { ...@@ -312,8 +265,8 @@ class CardCollectionState extends State<CardCollection> {
setState(() { setState(() {
cardModel.inputValue = value; cardModel.inputValue = value;
}); });
} },
) ),
) )
: new DefaultTextStyle.merge( : new DefaultTextStyle.merge(
context: context, context: context,
...@@ -324,12 +277,12 @@ class CardCollectionState extends State<CardCollection> { ...@@ -324,12 +277,12 @@ class CardCollectionState extends State<CardCollection> {
crossAxisAlignment: CrossAxisAlignment.stretch, crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[ children: <Widget>[
new Text(cardModel.inputValue.text, textAlign: _textAlign) new Text(cardModel.inputValue.text, textAlign: _textAlign),
] ],
) ),
) ),
) ),
) ),
); );
String backgroundMessage; String backgroundMessage;
...@@ -378,21 +331,21 @@ class CardCollectionState extends State<CardCollection> { ...@@ -378,21 +331,21 @@ class CardCollectionState extends State<CardCollection> {
new Expanded( new Expanded(
child: new Text(backgroundMessage, child: new Text(backgroundMessage,
style: backgroundTextStyle, style: backgroundTextStyle,
textAlign: TextAlign.center textAlign: TextAlign.center,
) ),
), ),
rightArrowIcon rightArrowIcon,
] ],
) ),
) ),
) ),
) ),
); );
return new IconTheme( return new IconTheme(
key: cardModel.key, key: cardModel.key,
data: const IconThemeData(color: Colors.white), data: const IconThemeData(color: Colors.white),
child: new Stack(children: <Widget>[background, card]) child: new Stack(children: <Widget>[background, card]),
); );
} }
...@@ -401,64 +354,43 @@ class CardCollectionState extends State<CardCollection> { ...@@ -401,64 +354,43 @@ class CardCollectionState extends State<CardCollection> {
begin: FractionalOffset.topLeft, begin: FractionalOffset.topLeft,
end: FractionalOffset.bottomLeft, end: FractionalOffset.bottomLeft,
colors: <Color>[const Color(0x00FFFFFF), const Color(0xFFFFFFFF)], colors: <Color>[const Color(0x00FFFFFF), const Color(0xFFFFFFFF)],
stops: <double>[0.1, 0.35] stops: <double>[0.1, 0.35],
) )
.createShader(bounds); .createShader(bounds);
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
Widget cardCollection; Widget cardCollection = new ListView.builder(
if (_fixedSizeCards) { itemExtent: _fixedSizeCards ? kFixedCardHeight : null,
cardCollection = new ScrollableList( itemCount: _cardModels.length,
snapOffsetCallback: _snapToCenter ? _toSnapOffset : null, itemBuilder: _buildCard,
itemExtent: kFixedCardHeight, );
children: _cardIndices.map<Widget>((int index) => _buildCard(context, index))
);
} else {
cardCollection = new LazyBlock(
delegate: new LazyBlockBuilder(builder: _buildCard),
snapOffsetCallback: _snapToCenter ? _toSnapOffset : null
);
}
if (_sunshine) { if (_sunshine) {
cardCollection = new Stack( cardCollection = new Stack(
children: <Widget>[ children: <Widget>[
new Column(children: <Widget>[new Image.network(_sunshineURL)]), new Column(children: <Widget>[new Image.network(_sunshineURL)]),
new ShaderMask(child: cardCollection, shaderCallback: _createShader) new ShaderMask(child: cardCollection, shaderCallback: _createShader),
] ],
); );
} }
Widget body = new Container( Widget body = new Container(
padding: const EdgeInsets.symmetric(vertical: 12.0, horizontal: 8.0), padding: const EdgeInsets.symmetric(vertical: 12.0, horizontal: 8.0),
decoration: new BoxDecoration(backgroundColor: _primaryColor[50]), decoration: new BoxDecoration(backgroundColor: _primaryColor[50]),
child: cardCollection child: cardCollection,
); );
if (_snapToCenter) {
Widget indicator = new IgnorePointer(
child: new Align(
alignment: FractionalOffset.centerLeft,
child: new Container(
height: 1.0,
decoration: new BoxDecoration(backgroundColor: const Color(0x80FFFFFF))
)
)
);
body = new Stack(children: <Widget>[body, indicator]);
}
return new Theme( return new Theme(
data: new ThemeData( data: new ThemeData(
primarySwatch: _primaryColor primarySwatch: _primaryColor,
), ),
child: new Scaffold( child: new Scaffold(
appBar: _buildAppBar(context), appBar: _buildAppBar(context),
drawer: _buildDrawer(), drawer: _buildDrawer(),
body: body body: body,
) ),
); );
} }
} }
...@@ -466,6 +398,6 @@ class CardCollectionState extends State<CardCollection> { ...@@ -466,6 +398,6 @@ class CardCollectionState extends State<CardCollection> {
void main() { void main() {
runApp(new MaterialApp( runApp(new MaterialApp(
title: 'Cards', title: 'Cards',
home: new CardCollection() home: new CardCollection(),
)); ));
} }
...@@ -8,10 +8,12 @@ import 'package:flutter/rendering.dart'; ...@@ -8,10 +8,12 @@ import 'package:flutter/rendering.dart';
class CardModel { class CardModel {
CardModel(this.value, this.height, this.color); CardModel(this.value, this.height, this.color);
int value; int value;
double height; double height;
Color color; Color color;
String get label => "Card $value";
String get label => 'Card $value';
Key get key => new ObjectKey(this); Key get key => new ObjectKey(this);
GlobalKey get targetKey => new GlobalObjectKey(this); GlobalKey get targetKey => new GlobalObjectKey(this);
} }
...@@ -21,7 +23,7 @@ enum MarkerType { topLeft, bottomRight, touch } ...@@ -21,7 +23,7 @@ enum MarkerType { topLeft, bottomRight, touch }
class _MarkerPainter extends CustomPainter { class _MarkerPainter extends CustomPainter {
const _MarkerPainter({ const _MarkerPainter({
this.size, this.size,
this.type this.type,
}); });
final double size; final double size;
...@@ -56,10 +58,10 @@ class _MarkerPainter extends CustomPainter { ...@@ -56,10 +58,10 @@ class _MarkerPainter extends CustomPainter {
class Marker extends StatelessWidget { class Marker extends StatelessWidget {
Marker({ Marker({
Key key,
this.type: MarkerType.touch, this.type: MarkerType.touch,
this.position, this.position,
this.size: 40.0, this.size: 40.0,
Key key
}) : super(key: key); }) : super(key: key);
final Point position; final Point position;
...@@ -77,10 +79,10 @@ class Marker extends StatelessWidget { ...@@ -77,10 +79,10 @@ class Marker extends StatelessWidget {
child: new CustomPaint( child: new CustomPaint(
painter: new _MarkerPainter( painter: new _MarkerPainter(
size: size, size: size,
type: type type: type,
) ),
) ),
) ),
); );
} }
} }
...@@ -92,7 +94,7 @@ class OverlayGeometryApp extends StatefulWidget { ...@@ -92,7 +94,7 @@ class OverlayGeometryApp extends StatefulWidget {
typedef void CardTapCallback(GlobalKey targetKey, Point globalPosition); typedef void CardTapCallback(GlobalKey targetKey, Point globalPosition);
class CardBuilder extends LazyBlockDelegate { class CardBuilder extends SliverChildDelegate {
CardBuilder({ this.cardModels, this.onTapUp }); CardBuilder({ this.cardModels, this.onTapUp });
final List<CardModel> cardModels; final List<CardModel> cardModels;
...@@ -102,7 +104,7 @@ class CardBuilder extends LazyBlockDelegate { ...@@ -102,7 +104,7 @@ class CardBuilder extends LazyBlockDelegate {
const TextStyle(color: Colors.white, fontSize: 18.0, fontWeight: FontWeight.bold); const TextStyle(color: Colors.white, fontSize: 18.0, fontWeight: FontWeight.bold);
@override @override
Widget buildItem(BuildContext context, int index) { Widget build(BuildContext context, int index) {
if (index >= cardModels.length) if (index >= cardModels.length)
return null; return null;
CardModel cardModel = cardModels[index]; CardModel cardModel = cardModels[index];
...@@ -115,20 +117,18 @@ class CardBuilder extends LazyBlockDelegate { ...@@ -115,20 +117,18 @@ class CardBuilder extends LazyBlockDelegate {
child: new Container( child: new Container(
height: cardModel.height, height: cardModel.height,
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
child: new Center(child: new Text(cardModel.label, style: cardLabelStyle)) child: new Center(child: new Text(cardModel.label, style: cardLabelStyle)),
) ),
) ),
); );
} }
@override @override
bool shouldRebuild(CardBuilder oldDelegate) { int get estimatedChildCount => cardModels.length;
return oldDelegate.cardModels != cardModels;
}
@override @override
double estimateTotalExtent(int firstIndex, int lastIndex, double minOffset, double firstStartOffset, double lastEndOffset) { bool shouldRebuild(CardBuilder oldDelegate) {
return (lastEndOffset - minOffset) * cardModels.length / (lastIndex + 1); return oldDelegate.cardModels != cardModels;
} }
} }
...@@ -144,7 +144,7 @@ class OverlayGeometryAppState extends State<OverlayGeometryApp> { ...@@ -144,7 +144,7 @@ class OverlayGeometryAppState extends State<OverlayGeometryApp> {
List<double> cardHeights = <double>[ List<double> cardHeights = <double>[
48.0, 63.0, 82.0, 146.0, 60.0, 55.0, 84.0, 96.0, 50.0, 48.0, 63.0, 82.0, 146.0, 60.0, 55.0, 84.0, 96.0, 50.0,
48.0, 63.0, 82.0, 146.0, 60.0, 55.0, 84.0, 96.0, 50.0, 48.0, 63.0, 82.0, 146.0, 60.0, 55.0, 84.0, 96.0, 50.0,
48.0, 63.0, 82.0, 146.0, 60.0, 55.0, 84.0, 96.0, 50.0 48.0, 63.0, 82.0, 146.0, 60.0, 55.0, 84.0, 96.0, 50.0,
]; ];
cardModels = new List<CardModel>.generate(cardHeights.length, (int i) { cardModels = new List<CardModel>.generate(cardHeights.length, (int i) {
Color color = Color.lerp(Colors.red[300], Colors.blue[900], i / cardHeights.length); Color color = Color.lerp(Colors.red[300], Colors.blue[900], i / cardHeights.length);
...@@ -152,15 +152,18 @@ class OverlayGeometryAppState extends State<OverlayGeometryApp> { ...@@ -152,15 +152,18 @@ class OverlayGeometryAppState extends State<OverlayGeometryApp> {
}); });
} }
void handleScroll(double offset) { bool handleScrollNotification(ScrollNotification2 notification) {
setState(() { if (notification is ScrollUpdateNotification && notification.depth == 1) {
double dy = markersScrollOffset - offset; setState(() {
markersScrollOffset = offset; double dy = markersScrollOffset - notification.metrics.extentBefore;
for (MarkerType type in markers.keys) { markersScrollOffset = notification.metrics.extentBefore;
Point oldPosition = markers[type]; for (MarkerType type in markers.keys) {
markers[type] = new Point(oldPosition.x, oldPosition.y + dy); Point oldPosition = markers[type];
} markers[type] = new Point(oldPosition.x, oldPosition.y + dy);
}); }
});
}
return false;
} }
void handleTapUp(GlobalKey target, Point globalPosition) { void handleTapUp(GlobalKey target, Point globalPosition) {
...@@ -182,15 +185,17 @@ class OverlayGeometryAppState extends State<OverlayGeometryApp> { ...@@ -182,15 +185,17 @@ class OverlayGeometryAppState extends State<OverlayGeometryApp> {
appBar: new AppBar(title: new Text('Tap a Card')), appBar: new AppBar(title: new Text('Tap a Card')),
body: new Container( body: new Container(
padding: const EdgeInsets.symmetric(vertical: 12.0, horizontal: 8.0), padding: const EdgeInsets.symmetric(vertical: 12.0, horizontal: 8.0),
child: new LazyBlock( child: new NotificationListener<ScrollNotification2>(
onScroll: handleScroll, onNotification: handleScrollNotification,
delegate: new CardBuilder( child: new ListView.custom(
cardModels: cardModels, childrenDelegate: new CardBuilder(
onTapUp: handleTapUp cardModels: cardModels,
) onTapUp: handleTapUp,
) ),
) ),
) ),
),
),
]; ];
for (MarkerType type in markers.keys) for (MarkerType type in markers.keys)
layers.add(new Marker(type: type, position: markers[type])); layers.add(new Marker(type: type, position: markers[type]));
...@@ -203,9 +208,9 @@ void main() { ...@@ -203,9 +208,9 @@ void main() {
theme: new ThemeData( theme: new ThemeData(
brightness: Brightness.light, brightness: Brightness.light,
primarySwatch: Colors.blue, primarySwatch: Colors.blue,
accentColor: Colors.redAccent[200] accentColor: Colors.redAccent[200],
), ),
title: 'Cards', title: 'Cards',
home: new OverlayGeometryApp() home: new OverlayGeometryApp(),
)); ));
} }
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