diff --git a/lib/animated_reorderable_list.dart b/lib/animated_reorderable_list.dart index 377db10..c3fd47b 100644 --- a/lib/animated_reorderable_list.dart +++ b/lib/animated_reorderable_list.dart @@ -5,3 +5,6 @@ export 'src/animated_gridview.dart'; export 'src/animated_listview.dart'; export 'src/animated_reorderable_gridview.dart'; export 'src/animated_reorderable_listview.dart'; + +//Direct access to the sliver builder, circumventing the ScrollView layer +export 'src/builder/reorderable_animated_list_impl.dart'; diff --git a/lib/src/builder/reorderable_animated_builder.dart b/lib/src/builder/reorderable_animated_builder.dart index 5aa39b9..e28c7ed 100644 --- a/lib/src/builder/reorderable_animated_builder.dart +++ b/lib/src/builder/reorderable_animated_builder.dart @@ -3,6 +3,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; +import '../component/sliver_constraints_capture.dart'; import '../component/drag_listener.dart'; import '../model/item_transition_data.dart'; import 'reorderable_animated_list_base.dart'; @@ -764,16 +765,18 @@ class ReorderableAnimatedBuilderState extends State @override Widget build(BuildContext context) { super.build(context); - return widget.delegateBuilder != null - ? SliverLayoutBuilder(builder: (context, constraints) { - _updateChildExtent(constraints); - return SliverGrid( - gridDelegate: widget.delegateBuilder!, - delegate: _createDelegate()); - }) + return widget.delegateBuilder != null + ? SliverConstraintsCapture( + onConstraintsChanged: _updateChildExtent, + child: SliverGrid( + gridDelegate: widget.delegateBuilder!, + delegate: _createDelegate(), + ), + ) : SliverList(delegate: _createDelegate()); } + Widget _itemBuilder(BuildContext context, int index) { final _ActiveItem? outgoingItem = _activeItemAt(_outgoingItems, index); final _ActiveItem? incomingItem = _activeItemAt(_incomingItems, index); diff --git a/lib/src/component/sliver_constraints_capture.dart b/lib/src/component/sliver_constraints_capture.dart new file mode 100644 index 0000000..9901c9e --- /dev/null +++ b/lib/src/component/sliver_constraints_capture.dart @@ -0,0 +1,74 @@ +import 'package:flutter/rendering.dart'; +import 'package:flutter/widgets.dart'; + +/// A widget that captures sliver constraints and notifies through a callback. +/// +/// This widget can be used to intercept the constraints passed to a sliver +/// without introducing a new build step, making it more efficient than using +/// [SliverLayoutBuilder]. +/// +/// Example: +/// ```dart +/// SliverConstraintsCapture( +/// onConstraintsChanged: (constraints) { +/// print('Sliver constraints: $constraints'); +/// }, +/// child: SliverList(...), +/// ) +/// ``` +class SliverConstraintsCapture extends SingleChildRenderObjectWidget { + /// Creates a widget that captures sliver constraints. + /// + /// The [onConstraintsChanged] callback will be called during layout + /// when the constraints are available. + /// + /// The [child] parameter is required and will be laid out normally. + const SliverConstraintsCapture({ + super.key, + required this.onConstraintsChanged, + required Widget child, + }) : super(child: child); + + /// Called during layout when sliver constraints are available. + /// + /// This callback can be used to read the constraints without triggering + /// an additional build. + final void Function(SliverConstraints constraints) onConstraintsChanged; + + @override + RenderObject createRenderObject(BuildContext context) { + return RenderSliverConstraintsCapture( + onConstraintsChanged: onConstraintsChanged, + ); + } + + @override + void updateRenderObject( + BuildContext context, RenderSliverConstraintsCapture renderObject) { + renderObject.onConstraintsChanged = onConstraintsChanged; + } +} + +/// Render object that captures sliver constraints during layout. +/// +/// This render object acts as a transparent proxy, passing through all +/// layout operations to its child while also notifying through a callback +/// when constraints are available. +class RenderSliverConstraintsCapture extends RenderProxySliver { + /// Creates a render object that captures sliver constraints. + /// + /// The [onConstraintsChanged] callback will be called during layout + /// when the constraints are available. + RenderSliverConstraintsCapture({ + required this.onConstraintsChanged, + }); + + /// Called during layout when sliver constraints are available. + void Function(SliverConstraints constraints) onConstraintsChanged; + + @override + void performLayout() { + onConstraintsChanged(constraints); + super.performLayout(); + } +}