You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
112 lines
2.6 KiB
Dart
112 lines
2.6 KiB
Dart
import 'package:flutter/rendering.dart';
|
|
import 'package:flutter/widgets.dart';
|
|
|
|
class AutoWrap extends StatefulWidget {
|
|
final List<Widget> children;
|
|
|
|
const AutoWrap({super.key, required this.children});
|
|
|
|
@override
|
|
State<StatefulWidget> createState() => _AutoWrapState();
|
|
}
|
|
|
|
class _AutoWrapState extends State<AutoWrap> {
|
|
var _computed = false;
|
|
var _isFirstBuild = true;
|
|
final Map<int, double> _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<Widget> 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);
|
|
}
|
|
}
|