grid padding

This commit is contained in:
Thibault Deckers 2022-03-25 17:46:24 +09:00
parent 3a81d6c655
commit 5a5e8d6728
7 changed files with 69 additions and 35 deletions

View file

@ -70,6 +70,7 @@ class _CollectionGridState extends State<CollectionGrid> {
extentMin: CollectionGrid.extentMin, extentMin: CollectionGrid.extentMin,
extentMax: CollectionGrid.extentMax, extentMax: CollectionGrid.extentMax,
spacing: CollectionGrid.spacing, spacing: CollectionGrid.spacing,
horizontalPadding: 2,
); );
return TileExtentControllerProvider( return TileExtentControllerProvider(
controller: _tileExtentController!, controller: _tileExtentController!,
@ -90,12 +91,13 @@ class _CollectionGridContent extends StatelessWidget {
final sectionedListLayoutProvider = ValueListenableBuilder<double>( final sectionedListLayoutProvider = ValueListenableBuilder<double>(
valueListenable: context.select<TileExtentController, ValueNotifier<double>>((controller) => controller.extentNotifier), valueListenable: context.select<TileExtentController, ValueNotifier<double>>((controller) => controller.extentNotifier),
builder: (context, thumbnailExtent, child) { builder: (context, thumbnailExtent, child) {
return Selector<TileExtentController, Tuple3<double, int, double>>( return Selector<TileExtentController, Tuple4<double, int, double, double>>(
selector: (context, c) => Tuple3(c.viewportSize.width, c.columnCount, c.spacing), selector: (context, c) => Tuple4(c.viewportSize.width, c.columnCount, c.spacing, c.horizontalPadding),
builder: (context, c, child) { builder: (context, c, child) {
final scrollableWidth = c.item1; final scrollableWidth = c.item1;
final columnCount = c.item2; final columnCount = c.item2;
final tileSpacing = c.item3; final tileSpacing = c.item3;
final horizontalPadding = c.item4;
return GridTheme( return GridTheme(
extent: thumbnailExtent, extent: thumbnailExtent,
child: EntryListDetailsTheme( child: EntryListDetailsTheme(
@ -117,6 +119,7 @@ class _CollectionGridContent extends StatelessWidget {
tileLayout: tileLayout, tileLayout: tileLayout,
columnCount: columnCount, columnCount: columnCount,
spacing: tileSpacing, spacing: tileSpacing,
horizontalPadding: horizontalPadding,
tileExtent: thumbnailExtent, tileExtent: thumbnailExtent,
tileBuilder: (entry) => AnimatedBuilder( tileBuilder: (entry) => AnimatedBuilder(
animation: favourites, animation: favourites,
@ -242,7 +245,9 @@ class _CollectionScaler extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final tileSpacing = context.select<TileExtentController, double>((controller) => controller.spacing); final metrics = context.select<TileExtentController, Tuple2<double, double>>((v) => Tuple2(v.spacing, v.horizontalPadding));
final tileSpacing = metrics.item1;
final horizontalPadding = metrics.item2;
return GridScaleGestureDetector<AvesEntry>( return GridScaleGestureDetector<AvesEntry>(
scrollableKey: scrollableKey, scrollableKey: scrollableKey,
tileLayout: tileLayout, tileLayout: tileLayout,
@ -253,6 +258,7 @@ class _CollectionScaler extends StatelessWidget {
tileCenter: center, tileCenter: center,
tileSize: tileSize, tileSize: tileSize,
spacing: tileSpacing, spacing: tileSpacing,
horizontalPadding: horizontalPadding,
borderWidth: DecoratedThumbnail.borderWidth, borderWidth: DecoratedThumbnail.borderWidth,
borderRadius: Radius.zero, borderRadius: Radius.zero,
color: DecoratedThumbnail.borderColor, color: DecoratedThumbnail.borderColor,

View file

@ -16,6 +16,7 @@ class SectionedEntryListLayoutProvider extends SectionedListLayoutProvider<AvesE
required TileLayout tileLayout, required TileLayout tileLayout,
required int columnCount, required int columnCount,
required double spacing, required double spacing,
required double horizontalPadding,
required double tileExtent, required double tileExtent,
required Widget Function(AvesEntry entry) tileBuilder, required Widget Function(AvesEntry entry) tileBuilder,
required Duration tileAnimationDelay, required Duration tileAnimationDelay,
@ -26,6 +27,7 @@ class SectionedEntryListLayoutProvider extends SectionedListLayoutProvider<AvesE
tileLayout: tileLayout, tileLayout: tileLayout,
columnCount: columnCount, columnCount: columnCount,
spacing: spacing, spacing: spacing,
horizontalPadding: horizontalPadding,
tileWidth: tileExtent, tileWidth: tileExtent,
tileHeight: tileExtent, tileHeight: tileExtent,
tileBuilder: tileBuilder, tileBuilder: tileBuilder,

View file

@ -108,19 +108,26 @@ class _GridScaleGestureDetectorState<T> extends State<GridScaleGestureDetector<T
_startSize = renderMetaData.size; _startSize = renderMetaData.size;
_scaledSizeNotifier = ValueNotifier(_startSize!); _scaledSizeNotifier = ValueNotifier(_startSize!);
// not the same as `MediaQuery.size.width`, because of screen insets/padding // not the same as `MediaQuery` metrics, because of screen insets/padding
final gridWidth = scrollableBox.size.width; final scrollViewWidth = scrollableBox.size.width;
final scrollViewXMin = scrollableBox.localToGlobal(Offset.zero).dx;
final scrollViewXMax = scrollableBox.localToGlobal(Offset(scrollViewWidth, 0)).dx;
final horizontalPadding = tileExtentController.horizontalPadding;
final xMin = scrollViewXMin + horizontalPadding;
final xMax = scrollViewXMax - horizontalPadding;
_extentMin = tileExtentController.effectiveExtentMin; _extentMin = tileExtentController.effectiveExtentMin;
_extentMax = tileExtentController.effectiveExtentMax; _extentMax = tileExtentController.effectiveExtentMax;
final halfSize = _startSize! / 2; final halfSize = _startSize! / 2;
final tileCenter = renderMetaData.localToGlobal(Offset(halfSize.width, halfSize.height)); final tileCenter = renderMetaData.localToGlobal(Offset(halfSize.width, halfSize.height));
final tileLayout = widget.tileLayout;
_overlayEntry = OverlayEntry( _overlayEntry = OverlayEntry(
builder: (context) => _ScaleOverlay( builder: (context) => _ScaleOverlay(
builder: (scaledTileSize) { builder: (scaledTileSize) {
late final double themeExtent; late final double themeExtent;
switch (widget.tileLayout) { switch (tileLayout) {
case TileLayout.grid: case TileLayout.grid:
themeExtent = scaledTileSize.width; themeExtent = scaledTileSize.width;
break; break;
@ -136,9 +143,10 @@ class _GridScaleGestureDetectorState<T> extends State<GridScaleGestureDetector<T
), ),
); );
}, },
tileLayout: widget.tileLayout, tileLayout: tileLayout,
center: tileCenter, center: tileCenter,
viewportWidth: gridWidth, xMin: xMin,
xMax: xMax,
gridBuilder: widget.gridBuilder, gridBuilder: widget.gridBuilder,
scaledSizeNotifier: _scaledSizeNotifier!, scaledSizeNotifier: _scaledSizeNotifier!,
), ),
@ -220,7 +228,7 @@ class _ScaleOverlay extends StatefulWidget {
final Widget Function(Size scaledTileSize) builder; final Widget Function(Size scaledTileSize) builder;
final TileLayout tileLayout; final TileLayout tileLayout;
final Offset center; final Offset center;
final double viewportWidth; final double xMin, xMax;
final ValueNotifier<Size> scaledSizeNotifier; final ValueNotifier<Size> scaledSizeNotifier;
final Widget Function(Offset center, Size tileSize, Widget child) gridBuilder; final Widget Function(Offset center, Size tileSize, Widget child) gridBuilder;
@ -229,7 +237,8 @@ class _ScaleOverlay extends StatefulWidget {
required this.builder, required this.builder,
required this.tileLayout, required this.tileLayout,
required this.center, required this.center,
required this.viewportWidth, required this.xMin,
required this.xMax,
required this.scaledSizeNotifier, required this.scaledSizeNotifier,
required this.gridBuilder, required this.gridBuilder,
}) : super(key: key); }) : super(key: key);
@ -243,7 +252,9 @@ class _ScaleOverlayState extends State<_ScaleOverlay> {
Offset get center => widget.center; Offset get center => widget.center;
double get gridWidth => widget.viewportWidth; double get xMin => widget.xMin;
double get xMax => widget.xMax;
// `Color(0x00FFFFFF)` is different from `Color(0x00000000)` (or `Colors.transparent`) // `Color(0x00FFFFFF)` is different from `Color(0x00000000)` (or `Colors.transparent`)
// when used in gradients or lerping to it // when used in gradients or lerping to it
@ -269,8 +280,6 @@ class _ScaleOverlayState extends State<_ScaleOverlay> {
final width = scaledSize.width; final width = scaledSize.width;
final height = scaledSize.height; final height = scaledSize.height;
// keep scaled thumbnail within the screen // keep scaled thumbnail within the screen
final xMin = context.select<MediaQueryData, double>((mq) => mq.padding.left);
final xMax = xMin + gridWidth;
var dx = .0; var dx = .0;
if (center.dx - width / 2 < xMin) { if (center.dx - width / 2 < xMin) {
dx = xMin - (center.dx - width / 2); dx = xMin - (center.dx - width / 2);
@ -309,7 +318,7 @@ class _ScaleOverlayState extends State<_ScaleOverlay> {
gradientCenter = center; gradientCenter = center;
break; break;
case TileLayout.list: case TileLayout.list:
gradientCenter = Offset(context.isRtl ? gridWidth : 0, center.dy); gradientCenter = Offset(context.isRtl ? xMax : xMin, center.dy);
break; break;
} }
@ -351,7 +360,7 @@ class GridPainter extends CustomPainter {
final TileLayout tileLayout; final TileLayout tileLayout;
final Offset tileCenter; final Offset tileCenter;
final Size tileSize; final Size tileSize;
final double spacing, borderWidth; final double spacing, horizontalPadding, borderWidth;
final Radius borderRadius; final Radius borderRadius;
final Color color; final Color color;
final TextDirection textDirection; final TextDirection textDirection;
@ -361,6 +370,7 @@ class GridPainter extends CustomPainter {
required this.tileCenter, required this.tileCenter,
required this.tileSize, required this.tileSize,
required this.spacing, required this.spacing,
required this.horizontalPadding,
required this.borderWidth, required this.borderWidth,
required this.borderRadius, required this.borderRadius,
required this.color, required this.color,
@ -394,7 +404,7 @@ class GridPainter extends CustomPainter {
case TileLayout.list: case TileLayout.list:
chipSize = Size.square(tileSize.shortestSide); chipSize = Size.square(tileSize.shortestSide);
final chipCenterToEdge = chipSize.width / 2; final chipCenterToEdge = chipSize.width / 2;
chipCenter = Offset(textDirection == TextDirection.rtl ? size.width - chipCenterToEdge : chipCenterToEdge, tileCenter.dy); chipCenter = Offset(textDirection == TextDirection.rtl ? size.width - (chipCenterToEdge + horizontalPadding) : chipCenterToEdge + horizontalPadding, tileCenter.dy);
deltaColumn = 0; deltaColumn = 0;
strokeShader = ui.Gradient.linear( strokeShader = ui.Gradient.linear(
tileCenter - Offset(0, chipSize.shortestSide * 3), tileCenter - Offset(0, chipSize.shortestSide * 3),

View file

@ -15,7 +15,7 @@ abstract class SectionedListLayoutProvider<T> extends StatelessWidget {
final double scrollableWidth; final double scrollableWidth;
final TileLayout tileLayout; final TileLayout tileLayout;
final int columnCount; final int columnCount;
final double spacing, tileWidth, tileHeight; final double spacing, horizontalPadding, tileWidth, tileHeight;
final Widget Function(T item) tileBuilder; final Widget Function(T item) tileBuilder;
final Duration tileAnimationDelay; final Duration tileAnimationDelay;
final Widget child; final Widget child;
@ -26,6 +26,7 @@ abstract class SectionedListLayoutProvider<T> extends StatelessWidget {
required this.tileLayout, required this.tileLayout,
required int columnCount, required int columnCount,
required this.spacing, required this.spacing,
required this.horizontalPadding,
required double tileWidth, required double tileWidth,
required this.tileHeight, required this.tileHeight,
required this.tileBuilder, required this.tileBuilder,
@ -33,7 +34,7 @@ abstract class SectionedListLayoutProvider<T> extends StatelessWidget {
required this.child, required this.child,
}) : assert(scrollableWidth != 0), }) : assert(scrollableWidth != 0),
columnCount = tileLayout == TileLayout.list ? 1 : columnCount, columnCount = tileLayout == TileLayout.list ? 1 : columnCount,
tileWidth = tileLayout == TileLayout.list ? scrollableWidth : tileWidth, tileWidth = tileLayout == TileLayout.list ? scrollableWidth - (horizontalPadding * 2) : tileWidth,
super(key: key); super(key: key);
@override @override
@ -98,6 +99,7 @@ abstract class SectionedListLayoutProvider<T> extends StatelessWidget {
tileWidth: tileWidth, tileWidth: tileWidth,
tileHeight: tileHeight, tileHeight: tileHeight,
spacing: spacing, spacing: spacing,
horizontalPadding: horizontalPadding,
sectionLayouts: sectionLayouts, sectionLayouts: sectionLayouts,
); );
} }
@ -129,12 +131,15 @@ abstract class SectionedListLayoutProvider<T> extends StatelessWidget {
); );
children.add(animate ? _buildAnimation(context, itemGridIndex, item) : item); children.add(animate ? _buildAnimation(context, itemGridIndex, item) : item);
} }
return _GridRow( return Padding(
padding: EdgeInsets.symmetric(horizontal: horizontalPadding),
child: _GridRow(
width: tileWidth, width: tileWidth,
height: tileHeight, height: tileHeight,
spacing: spacing, spacing: spacing,
textDirection: Directionality.of(context), textDirection: Directionality.of(context),
children: children, children: children,
),
); );
} }
@ -168,6 +173,7 @@ abstract class SectionedListLayoutProvider<T> extends StatelessWidget {
properties.add(DoubleProperty('scrollableWidth', scrollableWidth)); properties.add(DoubleProperty('scrollableWidth', scrollableWidth));
properties.add(IntProperty('columnCount', columnCount)); properties.add(IntProperty('columnCount', columnCount));
properties.add(DoubleProperty('spacing', spacing)); properties.add(DoubleProperty('spacing', spacing));
properties.add(DoubleProperty('horizontalPadding', horizontalPadding));
properties.add(DoubleProperty('tileWidth', tileWidth)); properties.add(DoubleProperty('tileWidth', tileWidth));
properties.add(DoubleProperty('tileHeight', tileHeight)); properties.add(DoubleProperty('tileHeight', tileHeight));
properties.add(DiagnosticsProperty<bool>('showHeaders', showHeaders)); properties.add(DiagnosticsProperty<bool>('showHeaders', showHeaders));
@ -178,7 +184,7 @@ class SectionedListLayout<T> {
final Map<SectionKey, List<T>> sections; final Map<SectionKey, List<T>> sections;
final bool showHeaders; final bool showHeaders;
final int columnCount; final int columnCount;
final double tileWidth, tileHeight, spacing; final double tileWidth, tileHeight, spacing, horizontalPadding;
final List<SectionLayout> sectionLayouts; final List<SectionLayout> sectionLayouts;
const SectionedListLayout({ const SectionedListLayout({
@ -188,6 +194,7 @@ class SectionedListLayout<T> {
required this.tileWidth, required this.tileWidth,
required this.tileHeight, required this.tileHeight,
required this.spacing, required this.spacing,
required this.horizontalPadding,
required this.sectionLayouts, required this.sectionLayouts,
}); });
@ -205,7 +212,7 @@ class SectionedListLayout<T> {
final row = (sectionItemIndex / columnCount).floor(); final row = (sectionItemIndex / columnCount).floor();
final listIndex = sectionLayout.firstIndex + 1 + row; final listIndex = sectionLayout.firstIndex + 1 + row;
final left = tileWidth * column + spacing * (column - 1); final left = horizontalPadding + tileWidth * column + spacing * (column - 1);
final top = sectionLayout.indexToLayoutOffset(listIndex); final top = sectionLayout.indexToLayoutOffset(listIndex);
return Rect.fromLTWH(left, top, tileWidth, tileHeight); return Rect.fromLTWH(left, top, tileWidth, tileHeight);
} }
@ -225,7 +232,7 @@ class SectionedListLayout<T> {
if (dy < 0) return null; if (dy < 0) return null;
final row = dy ~/ (tileHeight + spacing); final row = dy ~/ (tileHeight + spacing);
final column = position.dx ~/ (tileWidth + spacing); final column = max(0, position.dx - horizontalPadding) ~/ (tileWidth + spacing);
final index = row * columnCount + column; final index = row * columnCount + column;
if (index >= section.length) return null; if (index >= section.length) return null;

View file

@ -7,7 +7,7 @@ import 'package:flutter/widgets.dart';
class TileExtentController { class TileExtentController {
final String settingsRouteKey; final String settingsRouteKey;
final int columnCountMin, columnCountDefault; final int columnCountMin, columnCountDefault;
final double spacing, extentMin, extentMax; final double extentMin, extentMax, spacing, horizontalPadding;
final ValueNotifier<double> extentNotifier = ValueNotifier(0); final ValueNotifier<double> extentNotifier = ValueNotifier(0);
late double userPreferredExtent; late double userPreferredExtent;
@ -22,6 +22,7 @@ class TileExtentController {
required this.extentMin, required this.extentMin,
required this.extentMax, required this.extentMax,
required this.spacing, required this.spacing,
required this.horizontalPadding,
}) { }) {
userPreferredExtent = settings.getTileExtent(settingsRouteKey); userPreferredExtent = settings.getTileExtent(settingsRouteKey);
settings.addListener(_onSettingsChanged); settings.addListener(_onSettingsChanged);
@ -68,11 +69,11 @@ class TileExtentController {
return newExtent; return newExtent;
} }
double _extentMax() => min(extentMax, (viewportSize.shortestSide - spacing * (columnCountMin - 1)) / columnCountMin); double _extentMax() => min(extentMax, (viewportSize.shortestSide - (horizontalPadding * 2) - spacing * (columnCountMin - 1)) / columnCountMin);
double _columnCountForExtent(double extent) => (viewportSize.width + spacing) / (extent + spacing); double _columnCountForExtent(double extent) => (viewportSize.width - (horizontalPadding * 2) + spacing) / (extent + spacing);
double _extentForColumnCount(int columnCount) => (viewportSize.width - spacing * (columnCount - 1)) / columnCount; double _extentForColumnCount(int columnCount) => (viewportSize.width - (horizontalPadding * 2) - spacing * (columnCount - 1)) / columnCount;
int _effectiveColumnCountMin() => _columnCountForExtent(_extentMax()).ceil(); int _effectiveColumnCountMin() => _columnCountForExtent(_extentMax()).ceil();
@ -94,7 +95,7 @@ class TileExtentController {
Duration getTileAnimationDelay(Duration pageTarget) { Duration getTileAnimationDelay(Duration pageTarget) {
final extent = extentNotifier.value; final extent = extentNotifier.value;
final columnCount = ((viewportSize.width + spacing) / (extent + spacing)).round(); final columnCount = ((viewportSize.width - (horizontalPadding * 2) + spacing) / (extent + spacing)).round();
final rowCount = (viewportSize.height + spacing) ~/ (extent + spacing); final rowCount = (viewportSize.height + spacing) ~/ (extent + spacing);
return pageTarget ~/ (columnCount + rowCount) * timeDilation; return pageTarget ~/ (columnCount + rowCount) * timeDilation;
} }

View file

@ -164,6 +164,7 @@ class _FilterGridState<T extends CollectionFilter> extends State<FilterGrid<T>>
extentMin: 60, extentMin: 60,
extentMax: 300, extentMax: 300,
spacing: 8, spacing: 8,
horizontalPadding: 2,
); );
return TileExtentControllerProvider( return TileExtentControllerProvider(
controller: _tileExtentController!, controller: _tileExtentController!,
@ -237,12 +238,13 @@ class _FilterGridContent<T extends CollectionFilter> extends StatelessWidget {
final sectionedListLayoutProvider = ValueListenableBuilder<double>( final sectionedListLayoutProvider = ValueListenableBuilder<double>(
valueListenable: context.select<TileExtentController, ValueNotifier<double>>((controller) => controller.extentNotifier), valueListenable: context.select<TileExtentController, ValueNotifier<double>>((controller) => controller.extentNotifier),
builder: (context, thumbnailExtent, child) { builder: (context, thumbnailExtent, child) {
return Selector<TileExtentController, Tuple3<double, int, double>>( return Selector<TileExtentController, Tuple4<double, int, double, double>>(
selector: (context, c) => Tuple3(c.viewportSize.width, c.columnCount, c.spacing), selector: (context, c) => Tuple4(c.viewportSize.width, c.columnCount, c.spacing, c.horizontalPadding),
builder: (context, c, child) { builder: (context, c, child) {
final scrollableWidth = c.item1; final scrollableWidth = c.item1;
final columnCount = c.item2; final columnCount = c.item2;
final tileSpacing = c.item3; final tileSpacing = c.item3;
final horizontalPadding = c.item4;
// do not listen for animation delay change // do not listen for animation delay change
final target = context.read<DurationsData>().staggeredAnimationPageTarget; final target = context.read<DurationsData>().staggeredAnimationPageTarget;
final tileAnimationDelay = context.read<TileExtentController>().getTileAnimationDelay(target); final tileAnimationDelay = context.read<TileExtentController>().getTileAnimationDelay(target);
@ -265,6 +267,7 @@ class _FilterGridContent<T extends CollectionFilter> extends StatelessWidget {
scrollableWidth: scrollableWidth, scrollableWidth: scrollableWidth,
columnCount: columnCount, columnCount: columnCount,
spacing: tileSpacing, spacing: tileSpacing,
horizontalPadding: horizontalPadding,
tileWidth: thumbnailExtent, tileWidth: thumbnailExtent,
tileHeight: tileHeight, tileHeight: tileHeight,
tileBuilder: (gridItem) { tileBuilder: (gridItem) {
@ -430,8 +433,10 @@ class _FilterScaler<T extends CollectionFilter> extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final tileSpacing = context.select<TileExtentController, double>((controller) => controller.spacing);
final textScaleFactor = context.select<MediaQueryData, double>((mq) => mq.textScaleFactor); final textScaleFactor = context.select<MediaQueryData, double>((mq) => mq.textScaleFactor);
final metrics = context.select<TileExtentController, Tuple2<double, double>>((v) => Tuple2(v.spacing, v.horizontalPadding));
final tileSpacing = metrics.item1;
final horizontalPadding = metrics.item2;
return GridScaleGestureDetector<FilterGridItem<T>>( return GridScaleGestureDetector<FilterGridItem<T>>(
scrollableKey: scrollableKey, scrollableKey: scrollableKey,
tileLayout: tileLayout, tileLayout: tileLayout,
@ -442,6 +447,7 @@ class _FilterScaler<T extends CollectionFilter> extends StatelessWidget {
tileCenter: center, tileCenter: center,
tileSize: tileSize, tileSize: tileSize,
spacing: tileSpacing, spacing: tileSpacing,
horizontalPadding: horizontalPadding,
borderWidth: AvesFilterChip.outlineWidth, borderWidth: AvesFilterChip.outlineWidth,
borderRadius: CoveredFilterChip.radius(tileSize.shortestSide), borderRadius: CoveredFilterChip.radius(tileSize.shortestSide),
color: Colors.grey.shade700, color: Colors.grey.shade700,

View file

@ -15,6 +15,7 @@ class SectionedFilterListLayoutProvider<T extends CollectionFilter> extends Sect
required TileLayout tileLayout, required TileLayout tileLayout,
required int columnCount, required int columnCount,
required double spacing, required double spacing,
required double horizontalPadding,
required double tileWidth, required double tileWidth,
required double tileHeight, required double tileHeight,
required Widget Function(FilterGridItem<T> gridItem) tileBuilder, required Widget Function(FilterGridItem<T> gridItem) tileBuilder,
@ -26,6 +27,7 @@ class SectionedFilterListLayoutProvider<T extends CollectionFilter> extends Sect
tileLayout: tileLayout, tileLayout: tileLayout,
columnCount: columnCount, columnCount: columnCount,
spacing: spacing, spacing: spacing,
horizontalPadding: horizontalPadding,
tileWidth: tileWidth, tileWidth: tileWidth,
tileHeight: tileHeight, tileHeight: tileHeight,
tileBuilder: tileBuilder, tileBuilder: tileBuilder,