import 'package:flutter/rendering.dart'; import 'package:flutter/widgets.dart'; class AutoWrap extends StatefulWidget { final List children; const AutoWrap({super.key, required this.children}); @override State createState() => _AutoWrapState(); } class _AutoWrapState extends State { var _computed = false; var _isFirstBuild = true; final Map _childWidth = {}; var _isRow = true; void handleSizeChange(Size size, int id) { _childWidth[id] = size.width; } @override void didUpdateWidget(covariant AutoWrap oldWidget) { super.didUpdateWidget(oldWidget); if (_isFirstBuild) { _isFirstBuild = false; var sum = _childWidth.values.reduce((value, element) => value + element); var width = context.size?.width ?? 0; setState(() { _computed = true; _isRow = sum < width; }); } } @override Widget build(BuildContext context) { if (!_computed) { List stackChildren = []; for (var i = 0; i < widget.children.length; i++) { // Only first child is visible stackChildren.add( Opacity( opacity: i == 0 ? 1 : 0, child: WidgetSizeOffsetWrapper( id: i, onSizeChange: handleSizeChange, child: widget.children[i], ), ), ); } return Stack( children: stackChildren, ); } else { if (_isRow) { return Row(children: widget.children); } else { return Column(children: widget.children); } } } } typedef OnWidgetSizeChange = void Function(Size size, int id); class WidgetSizeRenderObject extends RenderProxyBox { final OnWidgetSizeChange onSizeChange; final int id; Size? currentSize; WidgetSizeRenderObject(this.onSizeChange, this.id); @override void performLayout() { super.performLayout(); try { Size? newSize = child?.size; if (newSize != null && currentSize != newSize) { currentSize = newSize; WidgetsBinding.instance.addPostFrameCallback((_) { onSizeChange(newSize, id); }); } } catch (e) { print(e); } } } class WidgetSizeOffsetWrapper extends SingleChildRenderObjectWidget { final OnWidgetSizeChange onSizeChange; final int id; const WidgetSizeOffsetWrapper({ Key? key, required this.onSizeChange, required this.id, required Widget child, }) : super(key: key, child: child); @override RenderObject createRenderObject(BuildContext context) { return WidgetSizeRenderObject(onSizeChange, id); } }