Make pesto demo scroll fast (#4443)
We can viewport the content using a ScrollableGrid. Also, we can use the padding mechanisms of the grid to avoid extra padding widgets.
This commit is contained in:
parent
440aa5ee2f
commit
6e530ea862
@ -69,22 +69,19 @@ class _PestoDemoState extends State<PestoDemo> {
|
||||
child: new Icon(icon: Icons.edit),
|
||||
onPressed: () { }
|
||||
),
|
||||
body: new Block(
|
||||
padding: new EdgeInsets.only(top: _kAppBarHeight + statusBarHeight),
|
||||
children: <Widget>[
|
||||
new Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: new MaxTileWidthGrid(
|
||||
maxTileWidth: 500.0,
|
||||
children: recipes.map(
|
||||
(Recipe recipe) => new _RecipeCard(
|
||||
recipe: recipe,
|
||||
onTap: () { _showRecipe(context, recipe); }
|
||||
)
|
||||
).toList()
|
||||
)
|
||||
body: new ScrollableGrid(
|
||||
delegate: new MaxTileWidthGridDelegate(
|
||||
maxTileWidth: 500.0,
|
||||
rowSpacing: 8.0,
|
||||
columnSpacing: 8.0,
|
||||
padding: new EdgeInsets.fromLTRB(8.0, 8.0 + _kAppBarHeight + statusBarHeight, 8.0, 8.0)
|
||||
),
|
||||
children: recipes.map(
|
||||
(Recipe recipe) => new _RecipeCard(
|
||||
recipe: recipe,
|
||||
onTap: () { _showRecipe(context, recipe); }
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
@ -200,42 +197,39 @@ class _RecipeCard extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return new Padding(
|
||||
padding: const EdgeInsets.all(4.0),
|
||||
child: new GestureDetector(
|
||||
onTap: onTap,
|
||||
child: new Card(
|
||||
child: new Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
new AssetImage(
|
||||
name: recipe.imagePath,
|
||||
fit: ImageFit.scaleDown
|
||||
),
|
||||
new Flexible(
|
||||
child: new Row(
|
||||
children: <Widget>[
|
||||
new Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: new AssetImage(
|
||||
width: 48.0,
|
||||
height: 48.0,
|
||||
name: recipe.ingredientsImagePath
|
||||
)
|
||||
),
|
||||
new Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
new Text(recipe.name, style: titleStyle),
|
||||
new Text(recipe.author, style: authorStyle),
|
||||
]
|
||||
return new GestureDetector(
|
||||
onTap: onTap,
|
||||
child: new Card(
|
||||
child: new Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
new AssetImage(
|
||||
name: recipe.imagePath,
|
||||
fit: ImageFit.scaleDown
|
||||
),
|
||||
new Flexible(
|
||||
child: new Row(
|
||||
children: <Widget>[
|
||||
new Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: new AssetImage(
|
||||
width: 48.0,
|
||||
height: 48.0,
|
||||
name: recipe.ingredientsImagePath
|
||||
)
|
||||
]
|
||||
)
|
||||
),
|
||||
new Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
new Text(recipe.name, style: titleStyle),
|
||||
new Text(recipe.author, style: authorStyle),
|
||||
]
|
||||
)
|
||||
]
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
);
|
||||
|
@ -27,11 +27,11 @@ bool _debugIsMonotonic(List<double> offsets) {
|
||||
return result;
|
||||
}
|
||||
|
||||
List<double> _generateRegularOffsets(int count, double size) {
|
||||
List<double> _generateRegularOffsets(int count, double extent) {
|
||||
final int length = count + 1;
|
||||
final List<double> result = new Float64List(length);
|
||||
for (int i = 0; i < length; ++i)
|
||||
result[i] = i * size;
|
||||
result[i] = i * extent;
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -62,20 +62,26 @@ class GridSpecification {
|
||||
}
|
||||
|
||||
/// Creates a grid specification containing a certain number of equally sized tiles.
|
||||
/// The tileWidth is the sum of the width of the child it will contain and
|
||||
/// columnSpacing (even if columnCount is 1). Similarly tileHeight is child's height
|
||||
/// plus rowSpacing. If the tiles are to completely fill the grid, then their size
|
||||
/// should be based on the grid's padded interior.
|
||||
///
|
||||
/// The `tileWidth` and `tileHeight` is the horizontal and vertical
|
||||
/// (respectively) extent that each child will be allocated in the grid. The
|
||||
/// tiles will have [columnSpacing] space between them horizontally and
|
||||
/// [rowSpacing] space between them vertically.
|
||||
///
|
||||
/// If the tiles are to completely fill the grid, then their size should be
|
||||
/// based on the grid's padded interior and the column and row spacing.
|
||||
GridSpecification.fromRegularTiles({
|
||||
double tileWidth,
|
||||
double tileHeight,
|
||||
int columnCount,
|
||||
int rowCount,
|
||||
this.rowSpacing: 0.0,
|
||||
this.columnSpacing: 0.0,
|
||||
double columnSpacing: 0.0,
|
||||
double rowSpacing: 0.0,
|
||||
this.padding: EdgeInsets.zero
|
||||
}) : columnOffsets = _generateRegularOffsets(columnCount, tileWidth),
|
||||
rowOffsets = _generateRegularOffsets(rowCount, tileHeight) {
|
||||
}) : columnOffsets = _generateRegularOffsets(columnCount, tileWidth + columnSpacing),
|
||||
rowOffsets = _generateRegularOffsets(rowCount, tileHeight + rowSpacing),
|
||||
columnSpacing = columnSpacing,
|
||||
rowSpacing = rowSpacing {
|
||||
assert(_debugIsMonotonic(columnOffsets));
|
||||
assert(_debugIsMonotonic(rowOffsets));
|
||||
assert(columnSpacing != null && columnSpacing >= 0.0);
|
||||
@ -85,10 +91,14 @@ class GridSpecification {
|
||||
|
||||
/// The offsets of the column boundaries in the grid.
|
||||
///
|
||||
/// The first offset is the offset of the left edge of the left-most column
|
||||
/// The first offset is the offset of the left edge of the left-most tile
|
||||
/// from the left edge of the interior of the grid's padding (0.0 if the padding
|
||||
/// is EdgeOffsets.zero). The last offset is the offset of the right edge of
|
||||
/// the right-most column from the left edge of the interior of the grid's padding.
|
||||
/// is EdgeOffsets.zero). The difference between successive entries is the
|
||||
/// tile width plus the column spacing.
|
||||
///
|
||||
/// The last offset is the offset of the right edge of the right-most tile
|
||||
/// from the left edge of the interior of the grid's padding (less the
|
||||
/// [columnSpacing]).
|
||||
///
|
||||
/// If there are n columns in the grid, there should be n + 1 entries in this
|
||||
/// list. The right edge of the last column is defined as columnOffsets(n), i.e.
|
||||
@ -97,22 +107,26 @@ class GridSpecification {
|
||||
|
||||
/// The offsets of the row boundaries in the grid.
|
||||
///
|
||||
/// The first offset is the offset of the top edge of the top-most row from
|
||||
/// The first offset is the offset of the top edge of the top-most tile from
|
||||
/// the top edge of the interior of the grid's padding (usually if the padding
|
||||
/// is EdgeOffsets.zero). The last offset is the offset of the bottom edge of
|
||||
/// the bottom-most column from the top edge of the interior of the grid's padding.
|
||||
/// is EdgeOffsets.zero). The difference between successive entries is the
|
||||
/// tile height plus the row spacing
|
||||
///
|
||||
/// The last offset is the offset of the bottom edge of the bottom-most tile
|
||||
/// from the top edge of the interior of the grid's padding. (less the
|
||||
/// [rowSpacing])
|
||||
///
|
||||
/// If there are n rows in the grid, there should be n + 1 entries in this
|
||||
/// list. The bottom edge of the last row is defined as rowOffsets(n), i.e.
|
||||
/// the top edge of an extra row.
|
||||
final List<double> rowOffsets;
|
||||
|
||||
/// The vertical distance between rows.
|
||||
final double rowSpacing;
|
||||
|
||||
/// The horizontal distance between columns.
|
||||
/// The horizontal padding between columns.
|
||||
final double columnSpacing;
|
||||
|
||||
/// The vertical padding between rows.
|
||||
final double rowSpacing;
|
||||
|
||||
/// The interior padding of the grid.
|
||||
///
|
||||
/// The grid's size encloses the spaced rows and columns and is then inflated
|
||||
@ -120,7 +134,12 @@ class GridSpecification {
|
||||
final EdgeInsets padding;
|
||||
|
||||
/// The size of the grid.
|
||||
Size get gridSize => new Size(columnOffsets.last + padding.horizontal, rowOffsets.last + padding.vertical);
|
||||
Size get gridSize {
|
||||
return new Size(
|
||||
columnOffsets.last + padding.horizontal - columnSpacing,
|
||||
rowOffsets.last + padding.vertical - rowSpacing
|
||||
);
|
||||
}
|
||||
|
||||
/// The number of columns in this grid.
|
||||
int get columnCount => columnOffsets.length - 1;
|
||||
@ -271,10 +290,10 @@ abstract class GridDelegateWithInOrderChildPlacement extends GridDelegate {
|
||||
assert(padding != null && padding.isNonNegative);
|
||||
}
|
||||
|
||||
/// The horizontal distance between columns.
|
||||
/// The horizontal padding between columns.
|
||||
final double columnSpacing;
|
||||
|
||||
/// The vertical distance between rows.
|
||||
/// The vertical padding between rows.
|
||||
final double rowSpacing;
|
||||
|
||||
/// Insets for the entire grid.
|
||||
@ -327,9 +346,11 @@ class FixedColumnCountGridDelegate extends GridDelegateWithInOrderChildPlacement
|
||||
@override
|
||||
GridSpecification getGridSpecification(BoxConstraints constraints, int childCount) {
|
||||
assert(constraints.maxWidth < double.INFINITY);
|
||||
int rowCount = (childCount / columnCount).ceil();
|
||||
double tileWidth = math.max(0.0, constraints.maxWidth - padding.horizontal + columnSpacing) / columnCount;
|
||||
double tileHeight = tileWidth / tileAspectRatio;
|
||||
final int rowCount = (childCount / columnCount).ceil();
|
||||
final double interiorWidth = constraints.maxWidth - padding.horizontal;
|
||||
final double columnWidth = interiorWidth / columnCount;
|
||||
final double tileWidth = math.max(0.0, columnWidth - columnSpacing);
|
||||
final double tileHeight = tileWidth / tileAspectRatio;
|
||||
return new GridSpecification.fromRegularTiles(
|
||||
tileWidth: tileWidth,
|
||||
tileHeight: tileHeight,
|
||||
@ -416,10 +437,17 @@ class MaxTileWidthGridDelegate extends GridDelegateWithInOrderChildPlacement {
|
||||
);
|
||||
}
|
||||
final double gridWidth = math.max(0.0, constraints.maxWidth - padding.horizontal);
|
||||
int columnCount = (gridWidth / maxTileWidth).ceil();
|
||||
int rowCount = (childCount / columnCount).ceil();
|
||||
double tileWidth = gridWidth / columnCount;
|
||||
double tileHeight = tileWidth / tileAspectRatio;
|
||||
// We inflate the gridWidth by columnSpacing because the columnSpacing for
|
||||
// the rightmost tile in the grid doesn't actually consume space in the
|
||||
// grid because the rightmost tile is flush to the right interior edge of
|
||||
// the grid.
|
||||
final double totalColumnExtent = gridWidth + columnSpacing;
|
||||
final double maxColumnWidth = maxTileWidth + columnSpacing;
|
||||
final int columnCount = (totalColumnExtent / maxColumnWidth).ceil();
|
||||
final int rowCount = (childCount / columnCount).ceil();
|
||||
final double columnWidth = totalColumnExtent / columnCount;
|
||||
final double tileWidth = columnWidth - columnSpacing;
|
||||
final double tileHeight = tileWidth / tileAspectRatio;
|
||||
return new GridSpecification.fromRegularTiles(
|
||||
tileWidth: tileWidth,
|
||||
tileHeight: tileHeight,
|
||||
@ -618,13 +646,13 @@ class RenderGrid extends RenderVirtualViewport<GridParentData> {
|
||||
assert(placement.column + placement.columnSpan < _specification.columnOffsets.length);
|
||||
assert(placement.row + placement.rowSpan < _specification.rowOffsets.length);
|
||||
|
||||
double tileLeft = gridLeftPadding + _specification.columnOffsets[placement.column];
|
||||
double tileRight = gridLeftPadding + _specification.columnOffsets[placement.column + placement.columnSpan];
|
||||
double tileTop = gridTopPadding + _specification.rowOffsets[placement.row];
|
||||
double tileBottom = gridTopPadding + _specification.rowOffsets[placement.row + placement.rowSpan];
|
||||
final double tileLeft = gridLeftPadding + _specification.columnOffsets[placement.column];
|
||||
final double tileRight = gridLeftPadding + _specification.columnOffsets[placement.column + placement.columnSpan] - _specification.columnSpacing;
|
||||
final double tileTop = gridTopPadding + _specification.rowOffsets[placement.row];
|
||||
final double tileBottom = gridTopPadding + _specification.rowOffsets[placement.row + placement.rowSpan] - _specification.rowSpacing;
|
||||
|
||||
double childWidth = math.max(0.0, tileRight - tileLeft - _specification.columnSpacing);
|
||||
double childHeight = math.max(0.0, tileBottom - tileTop - _specification.rowSpacing);
|
||||
final double childWidth = math.max(0.0, tileRight - tileLeft);
|
||||
final double childHeight = math.max(0.0, tileBottom - tileTop);
|
||||
|
||||
child.layout(new BoxConstraints(
|
||||
minWidth: childWidth,
|
||||
|
Loading…
x
Reference in New Issue
Block a user