more_than_wrap 1.0.1 copy "more_than_wrap: ^1.0.1" to clipboard
more_than_wrap: ^1.0.1 copied to clipboard

A Flutter package that provides a custom Wrap widget with limited number of rows and optional overflow widget display.

โœจ more_than_wrap #

Wrap with a row limit โ€” and a real +N more widget.

pub package live demo license

Flutter's Wrap will happily grow forever. more_than_wrap stops after maxLines and drops a real overflow child at the end of the last row โ€” a chip, a button, whatever you build.

Only children that fit are mounted. Hidden items never sit in the tree. The overflow indicator is built during layout, so the first frame already has the correct count. No flash. No jump.

Chip tags capped at two rows with a real +5 more overflow child

๐ŸŽฏ Flutter 3.32+ required ยท Try the live demo โ†’


๐ŸŒˆ Features #

๐Ÿ“ Limited rows maxLines caps the height. Pass null and it behaves like a regular Wrap.
๐Ÿ’Ž Real overflow widget +3 more, a chip, a tappable button โ€” it's a normal child, not canvas text.
๐Ÿฆฅ Lazy inflate Overflowed children are unmounted. .builder doesn't even construct them.
๐ŸŽฌ Correct first frame Overflow is measured and rebuilt in the same layout pass.
๐Ÿงฉ Fits the indicator If +N is too wide, more children hide until it fits.
๐Ÿงญ Wrap-compatible packing spacing, runSpacing, alignment, runAlignment, crossAxisAlignment, RTL, clipBehavior.

Direction is always horizontal (Wrap with direction: Axis.horizontal). Vertical wrap is out of scope.

Perfect for tag clouds, filter chips, avatar stacks, compact label rows.


๐Ÿš€ Getting started #

dependencies:
  more_than_wrap: ^1.0.0
flutter pub get

That's it. Import and wrap.


๐Ÿงช Usage #

๐Ÿ“ฆ Children list #

Widgets in children are created up front; only those that fit are mounted.

import 'package:flutter/material.dart';
import 'package:more_than_wrap/more_than_wrap.dart';

LimitedWrap(
  maxLines: 2,
  spacing: 8,
  runSpacing: 4,
  overflowWidgetBuilder: (context, count) {
    return Chip(label: Text('+$count more'));
  },
  children: [
    for (final tag in tags) Chip(label: Text(tag)),
  ],
)

๐Ÿ—๏ธ Builder (lazy children) #

itemBuilder runs only for indices that need to be measured or shown. Everything past the visible prefix is never built.

LimitedWrap.builder(
  maxLines: 2,
  spacing: 8,
  runSpacing: 4,
  itemCount: tags.length,
  itemBuilder: (context, index) {
    return Chip(label: Text(tags[index]));
  },
  overflowWidgetBuilder: (context, count) {
    return ActionChip(
      label: Text('+$count more'),
      onPressed: () {
        // Expand, open a sheet, navigate, โ€ฆ
      },
    );
  },
)

๐Ÿ’ก Rule of thumb: .builder for long / expensive lists. The list constructor when the set is small and already in memory.

๐Ÿ’ฅ Overflow widget #

overflowWidgetBuilder is optional. Without it, children that do not fit are unmounted and nothing is shown in their place.

When provided, it is a LimitedWrapOverflowBuilder:

typedef LimitedWrapOverflowBuilder = Widget Function(
  BuildContext context,
  int overflowCount,
);
  • Called only when at least one child does not fit
  • overflowCount is always > 0
  • Not called at all when everything fits โ€” the overflow slot is not even mounted
  • The returned widget is a normal child: layout, hit testing, animation โ€” all work

If the indicator is wider than the leftover space on the last row, LimitedWrap hides more children (and bumps the count) until it fits. If that empties the last row and the indicator fits on the previous one โ€” it moves there.

โ™พ๏ธ Unlimited rows #

Omit maxLines (or pass null) to wrap like a regular Wrap. You can also omit overflowWidgetBuilder โ€” overflowed children are simply not mounted.

LimitedWrap(
  spacing: 8,
  runSpacing: 4,
  children: chips,
)

๐ŸŽจ Alignment (same names as Wrap) #

LimitedWrap(
  maxLines: 2,
  alignment: WrapAlignment.end,
  runAlignment: WrapAlignment.center,
  crossAxisAlignment: WrapCrossAlignment.center,
  textDirection: TextDirection.rtl,
  verticalDirection: VerticalDirection.down,
  clipBehavior: Clip.hardEdge,
  overflowWidgetBuilder: (context, count) => Text('+$count'),
  children: chips,
)
Parameter What it does
spacing โ†”๏ธ Gap between children in a row
runSpacing โ†•๏ธ Gap between rows
alignment Main-axis packing inside a row (start, end, center, spaceBetween, โ€ฆ)
runAlignment Where the rows sit if there is extra height
crossAxisAlignment Align children within a row (start, end, center)
textDirection LTR / RTL โ€” defaults to ambient Directionality
verticalDirection down (first row on top) or up
clipBehavior Clip if content overflows the incoming constraints

โš™๏ธ How it works #

LimitedWrap is not a thin wrapper around Wrap. It's a RenderObjectWidget that inflates children during layout, in the spirit of slivers:

  1. ๐Ÿงฑ Children are created from the start of the list until maxLines is filled.
  2. ๐Ÿ™ˆ Remaining items stay unmounted (overflowCount = itemCount - placedCount).
  3. ๐ŸŽฐ If overflowCount > 0 and overflowWidgetBuilder is set, an overflow slot is inserted and the builder runs inside performLayout (same idea as LayoutBuilder). Without a builder, overflowed children are simply left unmounted.
  4. ๐Ÿ” If the overflow widget still doesn't fit, the last visible child is unmounted, the count goes up, and the indicator is laid out again โ€” still in that layout pass.
  5. ๐Ÿ“ Positions then follow RenderWrap packing for a horizontal wrap.

Because the overflow widget is built in-layout, the first paint already has the correct +N. No one-frame flash of a wrong count. No hiding overflowed widgets with opacity or Offstage.

โš ๏ธ Intrinsic dimensions of the overflow slot are not supported (same limitation as LayoutBuilder). Give the indicator a concrete size, or let it size itself from the wrap's maxWidth.


๐ŸŽฎ Example #

The example app is a playground: tweak max lines, item width, and item count live. The web build is the live demo.

cd example
flutter run

๐Ÿ“ฌ Additional information #

Bug reports and PRs are very welcome. Need vertical wrap (direction: Axis.vertical) or intrinsic sizing of the overflow slot? Open an issue.

๐Ÿ“„ License #

BSD 3-Clause. See LICENSE and BSD-3-Clause.

1
likes
160
points
112
downloads
screenshot

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

A Flutter package that provides a custom Wrap widget with limited number of rows and optional overflow widget display.

Repository (GitHub)
View/report issues

Topics

#widget #layout #wrap #chips #overflow

License

BSD-3-Clause (license)

Dependencies

flutter

More

Packages that depend on more_than_wrap