| // Copyright 2013 The Flutter 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/foundation.dart'; |
| import 'package:flutter/rendering.dart'; |
| |
| /// Describes the placement of a child in a [RenderDynamicSliverGrid]. |
| class DynamicSliverGridGeometry extends SliverGridGeometry { |
| /// Creates an object that describes the placement of a child in a |
| /// [RenderDynamicSliverGrid]. |
| const DynamicSliverGridGeometry({ |
| required super.scrollOffset, |
| required super.crossAxisOffset, |
| required super.mainAxisExtent, |
| required super.crossAxisExtent, |
| }); |
| |
| /// Returns [BoxConstraints] that will be tight if the |
| /// [DynamicSliverGridLayout] has provided fixed extents, forcing the child to |
| /// have the required size. |
| /// |
| /// If the [mainAxisExtent] is [double.infinity] the child will be allowed to |
| /// choose its own size in the main axis. Similarly, an infinite |
| /// [crossAxisExtent] will result in the child sizing itself in the cross |
| /// axis. Otherwise, the provided cross axis size or the |
| /// [SliverConstraints.crossAxisExtent] will be used to create tight |
| /// constraints in the cross axis. |
| /// |
| /// This differs from [SliverGridGeometry.getBoxConstraints] in that it allows |
| /// loose constraints, allowing the child to be its preferred size, or within |
| /// a range of minimum and maximum extents. |
| @override |
| BoxConstraints getBoxConstraints(SliverConstraints constraints) { |
| final double mainMinExtent = mainAxisExtent.isFinite ? mainAxisExtent : 0; |
| final double crossMinExtent = |
| crossAxisExtent.isInfinite ? 0.0 : crossAxisExtent; |
| |
| switch (constraints.axis) { |
| case Axis.vertical: |
| return BoxConstraints( |
| minHeight: mainMinExtent, |
| maxHeight: mainAxisExtent, |
| minWidth: crossMinExtent, |
| maxWidth: crossAxisExtent, |
| ); |
| case Axis.horizontal: |
| return BoxConstraints( |
| minHeight: crossMinExtent, |
| maxHeight: crossAxisExtent, |
| minWidth: mainMinExtent, |
| maxWidth: mainAxisExtent, |
| ); |
| } |
| } |
| } |
| |
| /// Manages the size and position of all the tiles in a [RenderSliverGrid]. |
| /// |
| /// Rather than providing a grid with a [SliverGridLayout] directly, you instead |
| /// provide the grid with a [SliverGridDelegate], which can compute a |
| /// [SliverGridLayout] given the current [SliverConstraints]. |
| /// |
| /// {@template dynamicLayouts.garbageCollection} |
| /// This grid does not currently collect leading garbage as the user scrolls |
| /// further down. This is because the current implementation requires the |
| /// leading tiles to maintain the current layout. Follow |
| /// [this github issue](https://github.com/flutter/flutter/issues/112234) for |
| /// tracking progress on dynamic leading garbage collection. |
| /// {@endtemplate} |
| abstract class DynamicSliverGridLayout extends SliverGridLayout { |
| /// The estimated size and position of the child with the given index. |
| /// |
| /// The [DynamicSliverGridGeometry] that is returned will |
| /// provide looser constraints to the child, whose size after layout can be |
| /// reported back to the layout object in [updateGeometryForChildIndex]. |
| @override |
| DynamicSliverGridGeometry getGeometryForChildIndex(int index); |
| |
| /// Update the size and position of the child with the given index, |
| /// considering the size of the child after layout. |
| /// |
| /// This is used to update the layout object after the child has laid out, |
| /// allowing the layout pattern to adapt to the child's size. |
| DynamicSliverGridGeometry updateGeometryForChildIndex( |
| int index, |
| Size childSize, |
| ); |
| |
| /// Called by [RenderDynamicSliverGrid] to validate the layout pattern has |
| /// filled the screen. |
| /// |
| /// A given child may have reached the target scroll offset of the current |
| /// layout pass, but there may still be more children to lay out based on the |
| /// pattern. |
| bool reachedTargetScrollOffset(double targetOffset); |
| |
| // These methods are not relevant to dynamic grid building, but extending the |
| // base [SliverGridLayout] class allows us to re-use existing |
| // [SliverGridDelegate]s like [SliverGridDelegateWithFixedCrossAxisCount] and |
| // [SliverGridDelegateWithMaxCrossAxisExtent]. |
| @override |
| @mustCallSuper |
| double computeMaxScrollOffset(int childCount) => throw UnimplementedError(); |
| @override |
| @mustCallSuper |
| int getMaxChildIndexForScrollOffset(double scrollOffset) => |
| throw UnimplementedError(); |
| @override |
| @mustCallSuper |
| int getMinChildIndexForScrollOffset(double scrollOffset) => |
| throw UnimplementedError(); |
| } |