Skip to content

Instantly share code, notes, and snippets.

@esDotDev
Created June 24, 2025 20:38
Show Gist options
  • Save esDotDev/34e1ca8dc28c40402c7057ef30364ccc to your computer and use it in GitHub Desktop.
Save esDotDev/34e1ca8dc28c40402c7057ef30364ccc to your computer and use it in GitHub Desktop.
import 'package:flutter/material.dart';
class DropExtraChildren extends StatelessWidget {
final Axis direction;
final double spacing;
final List<Widget> children;
const DropExtraChildren({
super.key,
this.direction = Axis.horizontal,
required this.spacing,
required this.children,
});
@override
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (context, constraints) {
return _DropExtraChildrenDelegate(
direction: direction,
spacing: spacing,
constraints: constraints,
children: children,
);
},
);
}
}
class _DropExtraChildrenDelegate extends MultiChildLayoutDelegate {
final Axis direction;
final double spacing;
final BoxConstraints constraints;
final List<Widget> children;
_DropExtraChildrenDelegate({
required this.direction,
required this.spacing,
required this.constraints,
required this.children,
});
@override
void performLayout(Size size) {
double mainAxisOffset = 0.0;
double crossAxisMax = 0.0;
int visibleCount = 0;
// Measure children and determine visible subset
for (int i = 0; i < children.length; i++) {
if (hasChild(i)) {
final childSize = layoutChild(
i,
BoxConstraints.loose(constraints.biggest),
);
final childMainExtent = (direction == Axis.horizontal)
? childSize.width
: childSize.height;
final childCrossExtent = (direction == Axis.horizontal)
? childSize.height
: childSize.width;
// Add spacing between items (except first)
final totalSpacing = (mainAxisOffset > 0) ? spacing : 0;
final newMainOffset = mainAxisOffset + totalSpacing + childMainExtent;
// Check against main axis constraints
final maxMainExtent = (direction == Axis.horizontal)
? constraints.maxWidth
: constraints.maxHeight;
if (newMainOffset <= maxMainExtent) {
mainAxisOffset = newMainOffset;
crossAxisMax = math.max(crossAxisMax, childCrossExtent);
visibleCount++;
} else {
break; // Stop processing remaining children
}
}
}
// Position visible children
double layoutOffset = 0.0;
for (int i = 0; i < visibleCount; i++) {
if (hasChild(i)) {
final childSize = getChildSize(i)!;
final childMainExtent = (direction == Axis.horizontal)
? childSize.width
: childSize.height;
// Apply spacing between items
if (i > 0) layoutOffset += spacing;
// Position child
if (direction == Axis.horizontal) {
positionChild(i, Offset(layoutOffset, 0));
} else {
positionChild(i, Offset(0, layoutOffset));
}
layoutOffset += childMainExtent;
}
}
// Set final size (main axis: visible children width, cross axis: max child height)
size = Size(
(direction == Axis.horizontal) ? layoutOffset : crossAxisMax,
(direction == Axis.horizontal) ? crossAxisMax : layoutOffset,
);
}
@override
bool shouldRelayout(_DropExtraChildrenDelegate oldDelegate) {
return oldDelegate.spacing != spacing ||
oldDelegate.direction != direction ||
oldDelegate.constraints != constraints ||
oldDelegate.children != children;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment