flexbox_layout 3.0.0 copy "flexbox_layout: ^3.0.0" to clipboard
flexbox_layout: ^3.0.0 copied to clipboard

CSS Flexbox layouts for Flutter: justified photo galleries, Pinterest-style masonry (waterfall) grids, and pinch-to-zoom scalable lists with high-performance sliver rendering.

Changelog #

All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

3.0.0 - 2026-06-12 #

Added #

  • Flexbox.clipBehavior is now honored: overflowing children are clipped by RenderFlexbox when a clip is requested (previously the parameter had no effect).
  • Horizontal scrollDirection support for FlexboxList, SliverFlexbox, DynamicFlexboxList and SliverDynamicFlexbox: child constraints and aspect-ratio orientation now follow the scroll axis.
  • lastChildLayoutTypeBuilder is now honored by SliverDynamicFlexbox: indices with a non-none LastChildLayoutType get a dedicated full cross-axis row sized to their natural extent (load-more footers).
  • RenderFlexbox reports a baseline, so a Flexbox can participate in baseline-aligned rows, and intrinsic main-axis sizes now include mainAxisSpacing.
  • FlexboxScaleController.gridModeTransitionBand and FlexboxScaleController.gridBlend: continuous morphing between the aspect-ratio layout and the uniform 1:1 grid while pinching, instead of a hard switch at gridModeThreshold.
  • FlexboxScaleController.focalPoint: the pinch gesture's focal point, meant to be read on demand during gestures (e.g. to anchor the zoom around the user's fingers).
  • SliverFlexboxDelegateWithDirectExtent.gridBlend: 1:1↔aspect-ratio morph control for the smooth zoom pipeline, typically driven by FlexboxScaleController.gridBlend.
  • SliverFlexbox.anchorOffsetFraction: when the flexbox delegate relayouts (e.g. during pinch zoom), the row at this viewport fraction stays visually stable via SliverGeometry.scrollOffsetCorrection; the anchor is re-based by same-frame scroll deltas so flings and zooms compose.
  • SliverScalableFlexbox.aspectRatios: per-child aspect ratios for non-uniform photo layouts in the packaged pinch-to-zoom widget.
  • SliverDynamicFlexbox now emits a SliverGeometry.scrollOffsetCorrection when rows above the viewport resize, so visible content no longer jumps.
  • MasonryFlexboxList and SliverMasonryFlexbox: a Pinterest-style masonry layout that packs each item into the currently shortest column (ties broken leftmost), with SliverMasonryFlexboxDelegateWithFixedCrossAxisCount and SliverMasonryFlexboxDelegateWithMaxCrossAxisExtent column strategies.
  • Three per-item sizing modes for masonry, mixable within one list: childAspectRatioBuilder (extent from a known ratio), childMainAxisExtentBuilder (explicit pixels), and a measured fallback for items whose builders return null (tight-cross / loose-main layout with debounced, threshold-gated updates).
  • SliverMasonryFlexboxDelegate.fullSpanBuilder: masonry items that span all columns (section headers, banners, load-more footers); columns equalize below a full-span item.
  • Masonry performance: positions come from a checkpointed placement cache, so steady scroll frames only touch attached children (builder-sized children are laid out exactly once), deep jumps in the builder-sized modes do not build the children in between, and placement shifts above the viewport are absorbed by a scroll-correction anchor.
  • SliverMasonryFlexbox.anchorOffsetFraction: the viewport fraction at which the masonry scroll-correction anchor is sampled (0.0 leading edge, 0.5 center), so placement shifts keep the item at that position stable — the masonry counterpart of SliverFlexbox.anchorOffsetFraction.
  • SliverScalableMasonryFlexbox: pinch-to-zoom masonry driven by a FlexboxScaleController whose currentExtent is the desired max column width. The continuous pinch extent is quantized at the widget layer into a discrete column count — extent changes within one band reuse the same delegate instance (zero relayout) and each count flip re-anchors around the gesture's focal point.

Changed #

  • Raised the minimum Flutter SDK to 3.32.0 and Dart SDK to 3.8.0.
  • FlexboxScaleController.mode direction is fixed: FlexboxScaleMode.grid1x1 now applies at small extents (currentExtent <= gridModeThreshold), so zooming items down past the threshold lands in the dense square grid like Google Photos. The previous behavior was inverted.
  • SliverScalableFlexbox was rebuilt on the smooth SliverFlexboxDelegateWithDirectExtent pipeline (it previously used SliverFlexboxDelegateWithMaxCrossAxisExtent, which jumped between column counts while zooming). It is now a StatefulWidget and listens to the full controller so fill-factor and grid-morph changes propagate every frame.
  • SliverFlexboxDelegateWithDirectExtent now lays out lazily — O(visible rows · log n) per frame instead of materializing every row — so pinch zoom stays smooth with thousands of photos. Aspect-ratio prefix sums are cached per aspectRatios list instance: reuse the same list instance across frames and pass a freshly built list only when the underlying data actually changes (documented on the delegate).
  • Flex resolution in RenderFlexbox is now purely arithmetic: static children are laid out exactly once per pass, and flexed/stretched children at most two to three times (previously up to four or more passes with O(n²) freeze loops).
  • Changing Flexbox.clipBehavior now only repaints instead of forcing a relayout.
  • The minimum intrinsic main size of a wrapping Flexbox now reports the largest single child (a wrapping container can always break lines) instead of the single-line sum; maxLines-capped containers keep the sum.
  • Optimized RenderFlexbox dry layout and layout scratch storage to avoid real child layout during dry measurement and reduce per-layout allocations.
  • Reworked RenderSliverDynamicFlexbox row caching: newly measured trailing children no longer invalidate already-built rows, cached rows are reused as a superset while scrolling backward, and getter-provided aspect ratios are re-validated only for attached children. This removes O(n) row rebuilds per scroll frame on long lists in both scroll directions.
  • Further SliverDynamicFlexbox scrolling work: deep scroll jumps re-anchor from the warm row cache instead of rebuilding rows from index 0, insert batches are sized from measured row extents (no same-frame child create/destroy churn), the row cache extends in place while scrolling (previously quadratic copying), configuration-equal delegate rebuilds keep the row cache, and children whose aspect ratios come from a getter are laid out once instead of twice.
  • A mid-list aspect-ratio change now repairs the row cache locally: only the affected rows are re-packed and the remaining rows are reused with shifted offsets, instead of rebuilding every row after the change. Debounced measure-mode changes take the same partial path by updating the cached ratio in place instead of fully invalidating the row cache.
  • SliverDynamicFlexbox steady-scroll hot path: the positioning loop now binary-searches the first attached row instead of scanning from row 0 (O(log n) instead of O(scroll depth) per frame), and cold deep jumps with a getter pack rows index-only — without building a single child — before anchoring (a 30k-pixel cold jump went from ~423 child builds to under 60).
  • SliverDynamicFlexbox.scrollExtent is now estimated from the exact cached row offsets plus a basis-locked per-item average, so the scrollbar no longer jitters while scrolling long unmeasured lists (adjacent-frame estimate drift dropped from tens of thousands of pixels to under one row).
  • Getter-provided aspect ratios are re-verified with the same maxAspectRatioChecksPerLayout/aspectRatioCheckInterval throttles as measure-mode probing (rotating through attached children across frames), with one unthrottled verification pass after every delegate swap.
  • Scroll-offset corrections below one millipixel are suppressed in both sliver render objects, avoiding floating-point-noise double layouts at extreme scroll offsets.
  • SliverFlexboxDelegateWithFixedCrossAxisCount and SliverFlexboxDelegateWithMaxCrossAxisExtent now produce a RegularSliverFlexboxLayout that answers all layout queries in O(1) arithmetic, so pinch-zoom extent changes and pagination growth no longer materialize every line on each pass; the previously unbounded per-child geometry cache was removed in its favor.
  • DimensionResolverMixin now coalesces bursts of resolved dimensions into a single rebuild and defers notification so synchronous resolutions are safe during build.
  • FlexboxScaleController sorts and validates snapPoints so zoom stepping behaves predictably with unsorted input.
  • Kept scroll cache configuration compatible with Flutter 3.32 while silencing newer-SDK deprecation noise.
  • Documented the item entrance animation system (README section, stagger batch model, and the stable animation id contract): lists that mutate anywhere but the tail must supply data-derived ids via animationIdBuilder / FlexboxItemTransition.animationId.

Removed #

  • Dead FlexLine members: left, top, right, bottom, dividerLengthInMainSize, goneItemCount, sumCrossSizeBefore, itemCountNotGone and updatePositionFromView(). They were never wired to the layout pipeline.

Fixed #

  • FlexboxScaleController.animateToExtent now settles exactly on its target extent when the spring completes (previously it rested within the solver tolerance of the target, which could leave zoomIn/zoomOut re-targeting the snap point they had just settled on).
  • Entrance animations (FlexboxItemTransition) no longer snap to completion when an ancestor rebuilds mid-animation, and the child element subtree is preserved after the animation completes (no state loss or flash).
  • Auto-mode entrance stagger re-anchors per attach batch: items attached by later frames (steady scroll-in) animate immediately instead of inheriting the initial batch's maximum clamped delay, and deep jumps cascade 0, 1, 2, ... instead of bursting simultaneously after a shared delay.
  • Entrance animation history is retained LRU-style: scrolling back over an item refreshes its id, so bounded histories (maxTrackedAnimationIds) on very long feeds no longer replay recently revisited items.
  • Enabling an entrance animation on an already-built item (manual-mode enqueue) no longer re-inflates the child element subtree, so child state survives the wrapper transition.
  • FlexboxItemTransition creates its AnimationController lazily — items that attach without animating (the dominant recycled scroll path) allocate no controller and no ticker — and pending stagger delays are cancellable timers, so disposed items are released immediately.
  • DimensionResolver.resolveCustom cancel/re-resolve cycles can no longer deliver stale results over newer ones (per-key generation tokens).
  • RenderSliverDynamicFlexbox invalidates index-keyed caches when the child list shrinks, so removed trailing items can no longer leave stale row geometry behind, and a partially attached boundary row is always filled to the end of the row before layout settles (no horizontal holes).
  • RenderSliverDynamicFlexbox also detects child-count growth: head or mid-list insertions invalidate stale index-keyed rows (sampled getter verification keeps the common append/load-more path cache-friendly), so a prepend no longer leaves misanchored leading rows behind.
  • Builder delegates without childCount now also recover from data-source shrinkage: reaching the end below the cached row coverage drops the stale trailing caches.
  • Jump-scrolling in measure mode backfills leading children only down to the first index whose ratios are already cached, instead of always materializing every child to index 0.
  • SliverDynamicFlexbox: debounced aspect-ratio updates applied while the app is idle now schedule their own relayout frame (previously the caches were updated but layout waited for the next unrelated frame).
  • alignSelf: AlignSelf.baseline now works without container-level baseline alignment (previously it produced negative offsets).
  • Baselines are collected after the final layout pass, so baseline alignment is no longer stale after a flex resize.
  • A flex item declaring inverted min/max constraints no longer triggers a clamp crash.
  • SliverFlexboxDelegateWithFlexValues clamps the available width when spacing exceeds a narrow viewport, so degenerate configurations produce zero-width items instead of negative geometry. Grid delegates and FlexChildInfo now assert positive aspect ratios and non-negative spacing in debug builds.
  • Flex items keep their cross-axis min/max constraints while growing or shrinking.
  • getDryLayout no longer corrupts live layout state.
  • Children that cannot compute a dry layout (e.g. LayoutBuilder) are fully supported in live layout passes.

2.0.0 - 2026-02-18 #

Added #

  • FlexboxItemAnimationController with auto/manual animation modes
  • FlexboxItemAnimationConfig and withFlexboxItemAnimation for staggered entrance transitions in sliver/list builders
  • FlexboxScaleController.extentListenable for extent-only UI subscriptions
  • maxAspectRatioChecksPerLayout and aspectRatioCheckInterval options in dynamic flexbox delegates

Changed #

  • Optimized sliver and render flexbox layout paths with delegate/layout caching
  • Improved dynamic aspect-ratio probing and relayout behavior for scrolling feeds
  • Updated scalable flexbox rebuilding from full controller listening to extent-only listening
  • Fixed max-lines behavior and defensive layout math in flexbox delegates
  • Updated and expanded test coverage for dynamic, sliver, scale-controller, and item-animation behavior

1.1.1 - 2026-01-17 #

Changed #

  • Enhanced documentation across all public APIs
  • Improved code comments and examples for better clarity
  • Comprehensive dart documentation coverage

1.1.0 - 2026-01-15 #

Added #

  • FlexboxScaleController - Controller for scalable flexbox with pinch-to-zoom support
    • Responsive scaling that follows pinch gestures in real-time
    • Smooth snap animation with spring physics
    • Mode switching between 1:1 grid and aspect ratio modes
    • Velocity-based momentum for natural gesture continuation
    • Configurable snap points, min/max extent, and grid mode threshold
  • FlexboxScaleMode enum - Display mode for scalable flexbox (grid1x1, aspectRatio)
  • SliverFlexboxDelegateWithDirectExtent - Delegate with direct extent control
    • Supports smooth continuous scaling without discrete column jumps
    • Fill factor interpolation for smooth layout transitions
    • Ideal for Google Photos-like pinch-to-zoom experience
  • SliverScalableFlexbox - Scalable sliver widget with pinch-to-zoom support
    • Automatically rebuilds when controller's extent changes
    • Integrates with CustomScrollView for seamless scrolling

Features #

  • Pinch-to-zoom gesture support for flexbox layouts
  • Spring physics animations for smooth snap transitions
  • Fill factor animation for smooth layout state transitions
  • Automatic display mode switching based on zoom level
  • Double-tap to zoom between predefined levels
  • Programmatic zoom control with zoomIn() and zoomOut() methods
  • Velocity-based gesture momentum for natural feel

Example #

  • Added ScalableFlexboxPage demonstrating pinch-to-zoom gallery
  • Network image gallery example with multiple image sources (Nekosia, Yande, Zerochan)

1.0.0 - 2026-01-14 #

Added #

  • Initial release of the Flutter Flexbox library
  • Flexbox widget - full CSS Flexbox layout implementation
  • FlexItem widget - wrapper for flex item properties
  • FlexboxList - scrollable list with flexbox layout capabilities
  • SliverFlexbox - sliver version for CustomScrollView
  • DynamicFlexboxList - auto-sizing flexbox list for variable content
  • SliverDynamicFlexbox - dynamic sliver for CustomScrollView
  • DimensionResolver - utility for measuring child dimensions
  • Multiple delegate types for different layout scenarios:
    • SliverFlexboxDelegateWithFixedCrossAxisCount
    • SliverFlexboxDelegateWithMaxCrossAxisExtent
    • SliverFlexboxDelegateWithAspectRatios
    • SliverFlexboxDelegateWithDynamicAspectRatios
    • SliverFlexboxDelegateWithFlexValues
    • SliverFlexboxDelegateWithBuilder

Features #

  • Full CSS Flexbox layout algorithm implementation
  • Support for flexDirection, flexWrap, justifyContent, alignItems, alignContent
  • Flex item properties: order, flexGrow, flexShrink, alignSelf, flexBasisPercent
  • Size constraints: minWidth, minHeight, maxWidth, maxHeight
  • wrapBefore property for explicit line breaks
  • Main axis and cross axis spacing
  • Item recycling for efficient scrolling
  • Dynamic sizing based on aspect ratios
  • Text direction support (LTR/RTL)
  • Max lines limitation for wrapped layouts
  • Configurable thresholds for layout updates:
    • aspectRatioChangeThreshold - minimum aspect ratio change to trigger update
    • crossAxisExtentChangeThreshold - viewport width change to clear cache
  • FlexboxList extends BoxScrollView for better framework integration
  • Comprehensive Dart documentation with examples for all public APIs

Example #

  • Complete example app with interactive playground
  • Demonstrations of all major features
  • Network image gallery example
4
likes
160
points
107
downloads

Documentation

Documentation
API reference

Publisher

verified publisherfluttercandies.com

Weekly Downloads

CSS Flexbox layouts for Flutter: justified photo galleries, Pinterest-style masonry (waterfall) grids, and pinch-to-zoom scalable lists with high-performance sliver rendering.

Repository (GitHub)
View/report issues

Topics

#ui #widget #layout #flexbox #masonry

License

MIT (license)

Dependencies

extended_list_library, flutter

More

Packages that depend on flexbox_layout