Commit 3ca92161 authored by Adam Barth's avatar Adam Barth Committed by GitHub

Remove ScrollableGrid (#8020)

All the clients have migrated to GridView.  Also, remove RenderGrid,
which isn't needed by GridView.
parent a49c854f
......@@ -32,7 +32,6 @@ export 'src/rendering/editable_line.dart';
export 'src/rendering/error.dart';
export 'src/rendering/flex.dart';
export 'src/rendering/flow.dart';
export 'src/rendering/grid.dart';
export 'src/rendering/image.dart';
export 'src/rendering/layer.dart';
export 'src/rendering/list.dart';
......
......@@ -55,7 +55,7 @@ Map<MaterialListType, double> kListItemExtent = const <MaterialListType, double>
/// * [ScrollableList], on which this widget is based.
/// * [TwoLevelList], for lists that have subsections that can collapse and
/// expand.
/// * [ScrollableGrid]
/// * [GridView]
/// * <https://material.google.com/components/lists.html>
class MaterialList extends StatelessWidget {
/// Creates a material list.
......
This diff is collapsed.
......@@ -19,19 +19,13 @@ export 'package:flutter/rendering.dart' show
CrossAxisAlignment,
CustomClipper,
CustomPainter,
FixedColumnCountGridDelegate,
FlexFit,
FlowDelegate,
FlowPaintingContext,
FractionalOffsetTween,
GridChildPlacement,
GridDelegate,
GridDelegateWithInOrderChildPlacement,
GridSpecification,
HitTestBehavior,
MainAxisAlignment,
MainAxisSize,
MaxTileWidthGridDelegate,
MultiChildLayoutDelegate,
Overflow,
PaintingContext,
......
......@@ -222,7 +222,7 @@ class LazyBlock extends StatelessWidget {
}
// Warning: keep the dartdoc comments that follow in sync with the copies in
// Scrollable, ScrollableGrid, ScrollableViewport, ScrollableList, and
// Scrollable, ScrollableViewport, ScrollableList, and
// ScrollableLazyList. And see: https://github.com/dart-lang/dartdoc/issues/1161.
/// The scroll offset this widget should use when first created.
......
......@@ -375,8 +375,8 @@ typedef double SnapOffsetCallback(double scrollOffset, Size containerSize);
/// If you have a list of widgets and want them to be able to scroll if there is
/// insufficient room, consider using [Block].
///
/// Commonly used classes that are based on Scrollable include [ScrollableList],
/// [ScrollableGrid], and [ScrollableViewport].
/// Commonly used classes that are based on Scrollable include [ScrollableList]
/// and [ScrollableViewport].
///
/// Widgets that subclass [Scrollable] typically use state objects that subclass
/// [ScrollableState].
......@@ -400,8 +400,8 @@ class Scrollable extends StatefulWidget {
}
// Warning: keep the dartdoc comments that follow in sync with the copies in
// ScrollableViewport, LazyBlock, ScrollableLazyList, ScrollableList, and
// ScrollableGrid. And see: https://github.com/dart-lang/dartdoc/issues/1161.
// ScrollableViewport and LazyBlock.
// And see: https://github.com/dart-lang/dartdoc/issues/1161.
/// The scroll offset this widget should use when first created.
final double initialScrollOffset;
......@@ -1244,7 +1244,7 @@ class ScrollNotification extends Notification {
///
/// * [Block], if your single child is a [Column].
/// * [ScrollableList], if you have many identically-sized children.
/// * [ScrollableGrid], if your children are in a grid pattern.
/// * [GridView], if your children are in a grid pattern.
/// * [LazyBlock], if you have many children of varying sizes.
class ScrollableViewport extends StatelessWidget {
/// Creates a simple scrolling widget that has a single child.
......@@ -1267,8 +1267,8 @@ class ScrollableViewport extends StatelessWidget {
}
// Warning: keep the dartdoc comments that follow in sync with the copies in
// Scrollable, LazyBlock, ScrollableLazyList, ScrollableList, and
// ScrollableGrid. And see: https://github.com/dart-lang/dartdoc/issues/1161.
// Scrollable, LazyBlock, ScrollableLazyList, and ScrollableList.
// And see: https://github.com/dart-lang/dartdoc/issues/1161.
/// The scroll offset this widget should use when first created.
final double initialScrollOffset;
......
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
////////////////////////////////////////////////////////////////////////////////
// DELETE THIS FILE WHEN REMOVING LEGACY SCROLLING CODE
////////////////////////////////////////////////////////////////////////////////
import 'dart:math' as math;
import 'package:collection/collection.dart' show lowerBound;
import 'package:flutter/foundation.dart';
import 'package:flutter/rendering.dart';
import 'framework.dart';
import 'scroll_configuration.dart';
import 'scrollable.dart';
import 'virtual_viewport.dart';
/// A vertically scrollable grid.
///
/// Requires that [delegate] places its children in row-major order.
///
/// See also:
///
/// * [CustomGrid].
/// * [ScrollableList].
/// * [ScrollableViewport].
class ScrollableGrid extends StatelessWidget {
/// Creates a vertically scrollable grid.
///
/// The [delegate] argument must not be null.
ScrollableGrid({
Key key,
this.initialScrollOffset,
this.onScrollStart,
this.onScroll,
this.onScrollEnd,
this.snapOffsetCallback,
this.scrollableKey,
@required this.delegate,
this.children: const <Widget>[],
}) : super(key: key) {
assert(delegate != null);
}
// Warning: keep the dartdoc comments that follow in sync with the copies in
// Scrollable, LazyBlock, ScrollableViewport, ScrollableList, and
// ScrollableLazyList. And see: https://github.com/dart-lang/dartdoc/issues/1161.
/// The scroll offset this widget should use when first created.
final double initialScrollOffset;
/// Called whenever this widget starts to scroll.
final ScrollListener onScrollStart;
/// Called whenever this widget's scroll offset changes.
final ScrollListener onScroll;
/// Called whenever this widget stops scrolling.
final ScrollListener onScrollEnd;
/// Called to determine the offset to which scrolling should snap,
/// when handling a fling.
///
/// This callback, if set, will be called with the offset that the
/// Scrollable would have scrolled to in the absence of this
/// callback, and a Size describing the size of the Scrollable
/// itself.
///
/// The callback's return value is used as the new scroll offset to
/// aim for.
///
/// If the callback simply returns its first argument (the offset),
/// then it is as if the callback was null.
final SnapOffsetCallback snapOffsetCallback;
/// The key for the Scrollable created by this widget.
final Key scrollableKey;
/// The delegate that controls the layout of the children.
///
/// For example, a [FixedColumnCountGridDelegate] for grids that have a fixed
/// number of columns or a [MaxTileWidthGridDelegate] for grids that have a
/// maximum tile width.
final GridDelegate delegate;
/// The children that will be placed in the grid.
final Iterable<Widget> children;
Widget _buildViewport(BuildContext context, ScrollableState state) {
return new GridViewport(
scrollOffset: state.scrollOffset,
delegate: delegate,
onExtentsChanged: state.handleExtentsChanged,
children: children
);
}
@override
Widget build(BuildContext context) {
final Widget result = new Scrollable(
key: scrollableKey,
initialScrollOffset: initialScrollOffset,
// TODO(abarth): Support horizontal offsets. For horizontally scrolling
// grids. For horizontally scrolling grids, we'll probably need to use a
// delegate that places children in column-major order.
scrollDirection: Axis.vertical,
onScrollStart: onScrollStart,
onScroll: onScroll,
onScrollEnd: onScrollEnd,
snapOffsetCallback: snapOffsetCallback,
builder: _buildViewport,
);
return ScrollConfiguration.wrap(context, result);
}
}
/// A virtual viewport onto a grid of widgets.
///
/// Used by [ScrollableGrid].
///
/// See also:
///
/// * [ListViewport].
/// * [LazyListViewport].
class GridViewport extends VirtualViewportFromIterable {
/// Creates a virtual viewport onto a grid of widgets.
///
/// The [delegate] argument must not be null.
GridViewport({
this.scrollOffset,
this.delegate,
this.onExtentsChanged,
this.children: const <Widget>[],
}) {
assert(delegate != null);
}
/// The [startOffset] without taking the [delegate]'s padding into account.
final double scrollOffset;
@override
double get startOffset {
if (delegate == null)
return scrollOffset;
return scrollOffset - delegate.padding.top;
}
/// The delegate that controls the layout of the children.
///
/// For example, a [FixedColumnCountGridDelegate] for grids that have a fixed
/// number of columns or a [MaxTileWidthGridDelegate] for grids that have a
/// maximum tile width.
final GridDelegate delegate;
/// Called when the interior or exterior dimensions of the viewport change.
final ExtentsChangedCallback onExtentsChanged;
@override
final Iterable<Widget> children;
@override
RenderGrid createRenderObject(BuildContext context) => new RenderGrid(delegate: delegate);
@override
_GridViewportElement createElement() => new _GridViewportElement(this);
}
class _GridViewportElement extends VirtualViewportElement {
_GridViewportElement(GridViewport widget) : super(widget);
@override
GridViewport get widget => super.widget;
@override
RenderGrid get renderObject => super.renderObject;
@override
int get materializedChildBase => _materializedChildBase;
int _materializedChildBase;
@override
int get materializedChildCount => _materializedChildCount;
int _materializedChildCount;
@override
double get startOffsetBase => _startOffsetBase;
double _startOffsetBase;
@override
double get startOffsetLimit =>_startOffsetLimit;
double _startOffsetLimit;
@override
void updateRenderObject(GridViewport oldWidget) {
renderObject.delegate = widget.delegate;
super.updateRenderObject(oldWidget);
}
double _lastReportedContentExtent;
double _lastReportedContainerExtent;
GridSpecification _specification;
@override
void layout(BoxConstraints constraints) {
_specification = renderObject.specification;
double contentExtent = _specification.gridSize.height;
double containerExtent = renderObject.size.height;
int materializedRowBase = math.max(0, lowerBound(_specification.rowOffsets, widget.startOffset) - 1);
int materializedRowLimit = math.min(_specification.rowCount, lowerBound(_specification.rowOffsets, widget.startOffset + containerExtent));
_materializedChildBase = (materializedRowBase * _specification.columnCount).clamp(0, renderObject.virtualChildCount);
_materializedChildCount = (materializedRowLimit * _specification.columnCount).clamp(0, renderObject.virtualChildCount) - _materializedChildBase;
_startOffsetBase = _specification.rowOffsets[materializedRowBase];
_startOffsetLimit = _specification.rowOffsets[materializedRowLimit] - containerExtent;
super.layout(constraints);
if (contentExtent != _lastReportedContentExtent || containerExtent != _lastReportedContainerExtent) {
_lastReportedContentExtent = contentExtent;
_lastReportedContainerExtent = containerExtent;
widget.onExtentsChanged(_lastReportedContentExtent, _lastReportedContainerExtent);
}
}
}
......@@ -61,8 +61,8 @@ class ScrollableList extends StatelessWidget {
}
// Warning: keep the dartdoc comments that follow in sync with the copies in
// Scrollable, LazyBlock, ScrollableLazyList, ScrollableViewport, and
// ScrollableGrid. And see: https://github.com/dart-lang/dartdoc/issues/1161.
// Scrollable, LazyBlock, ScrollableLazyList, ScrollableViewport.
// And see: https://github.com/dart-lang/dartdoc/issues/1161.
/// The scroll offset this widget should use when first created.
final double initialScrollOffset;
......@@ -450,8 +450,8 @@ class ScrollableLazyList extends StatelessWidget {
}
// Warning: keep the dartdoc comments that follow in sync with the copies in
// Scrollable, LazyBlock, ScrollableViewport, ScrollableList, and
// ScrollableGrid. And see: https://github.com/dart-lang/dartdoc/issues/1161.
// Scrollable, LazyBlock, ScrollableViewport, and ScrollableList.
// And see: https://github.com/dart-lang/dartdoc/issues/1161.
/// The scroll offset this widget should use when first created.
final double initialScrollOffset;
......
......@@ -23,8 +23,7 @@ import 'framework.dart';
/// the amount of the thing inside the viewport that is visible from outside
/// the viewport).
///
/// Used by [ScrollableGrid.onExtentsChanged],
/// [ScrollableList.onExtentsChanged], etc.
/// Used by [ScrollableList.onExtentsChanged], etc.
typedef void ExtentsChangedCallback(double contentExtent, double containerExtent);
/// An abstract widget whose children are not all materialized.
......
......@@ -55,7 +55,6 @@ export 'src/widgets/scroll_position.dart';
export 'src/widgets/scroll_simulation.dart';
export 'src/widgets/scroll_view.dart';
export 'src/widgets/scrollable.dart';
export 'src/widgets/scrollable_grid.dart';
export 'src/widgets/scrollable_list.dart';
export 'src/widgets/semantics_debugger.dart';
export 'src/widgets/single_child_scroll_view.dart';
......
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/rendering.dart';
import 'package:test/test.dart';
import 'rendering_tester.dart';
void main() {
test('Basic grid layout test', () {
List<RenderBox> children = <RenderBox>[
new RenderDecoratedBox(decoration: const BoxDecoration()),
new RenderDecoratedBox(decoration: const BoxDecoration()),
new RenderDecoratedBox(decoration: const BoxDecoration()),
new RenderDecoratedBox(decoration: const BoxDecoration())
];
RenderGrid grid = new RenderGrid(
children: children,
delegate: new MaxTileWidthGridDelegate(maxTileWidth: 100.0)
);
layout(grid, constraints: const BoxConstraints(maxWidth: 200.0));
children.forEach((RenderBox child) {
expect(child.size.width, equals(100.0), reason: "child width");
expect(child.size.height, equals(100.0), reason: "child height");
});
expect(grid.size.width, equals(200.0), reason: "grid width");
expect(grid.size.height, equals(200.0), reason: "grid height");
expect(grid.debugNeedsLayout, false);
grid.delegate = new MaxTileWidthGridDelegate(maxTileWidth: 60.0);
expect(grid.debugNeedsLayout, true);
pumpFrame();
children.forEach((RenderBox child) {
expect(child.size.width, equals(50.0), reason: "child width");
expect(child.size.height, equals(50.0), reason: "child height");
});
expect(grid.size.width, equals(200.0), reason: "grid width");
expect(grid.size.height, equals(50.0), reason: "grid height");
});
}
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';
void main() {
testWidgets('Empty GridView', (WidgetTester tester) async {
List<Widget> children = <Widget>[
new DecoratedBox(decoration: const BoxDecoration()),
new DecoratedBox(decoration: const BoxDecoration()),
new DecoratedBox(decoration: const BoxDecoration()),
new DecoratedBox(decoration: const BoxDecoration())
];
await tester.pumpWidget(new Center(
child: new Container(
width: 200.0,
child: new GridView.extent(
maxCrossAxisExtent: 100.0,
shrinkWrap: true,
children: children,
),
),
));
children.forEach((Widget child) {
RenderBox box = tester.renderObject(find.byConfig(child));
expect(box.size.width, equals(100.0), reason: "child width");
expect(box.size.height, equals(100.0), reason: "child height");
});
RenderBox grid = tester.renderObject(find.byType(GridView));
expect(grid.size.width, equals(200.0), reason: "grid width");
expect(grid.size.height, equals(200.0), reason: "grid height");
expect(grid.debugNeedsLayout, false);
await tester.pumpWidget(new Center(
child: new Container(
width: 200.0,
child: new GridView.extent(
maxCrossAxisExtent: 60.0,
shrinkWrap: true,
children: children,
),
),
));
children.forEach((Widget child) {
RenderBox box = tester.renderObject(find.byConfig(child));
expect(box.size.width, equals(50.0), reason: "child width");
expect(box.size.height, equals(50.0), reason: "child height");
});
expect(grid.size.width, equals(200.0), reason: "grid width");
expect(grid.size.height, equals(50.0), reason: "grid height");
});
}
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