import 'package:flutter/widgets.dart'; import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart'; import 'package:nc_photos/widget/draggable.dart' as my; import 'package:nc_photos/widget/measurable_item_list.dart'; abstract class DraggableItem { Widget buildWidget(BuildContext context); /// The widget to show under the pointer when a drag is under way. /// /// Return null if you wish to just use the same widget as display Widget? buildDragFeedbackWidget(BuildContext context) => null; bool get isDraggable => false; DragTargetAccept? get onDropBefore => null; DragTargetAccept? get onDropAfter => null; VoidCallback? get onDragStarted => null; VoidCallback? get onDragEndedAny => null; StaggeredTile get staggeredTile => const StaggeredTile.count(1, 1); } mixin DraggableItemListMixin on State { @protected Widget buildDraggableItemList({ required double maxCrossAxisExtent, ValueChanged? onMaxExtentChanged, }) { _maxCrossAxisExtent = maxCrossAxisExtent; return MeasurableItemList( maxCrossAxisExtent: maxCrossAxisExtent, itemCount: _items.length, itemBuilder: _buildItem, staggeredTileBuilder: (index) => _items[index].staggeredTile, onMaxExtentChanged: onMaxExtentChanged, ); } @protected set draggableItemList(List newItems) { _items = newItems; } Widget _buildItem(BuildContext context, int index) { final item = _items[index]; return my.Draggable( data: item, child: item.buildWidget(context), feedback: item.buildDragFeedbackWidget(context), onDropBefore: item.onDropBefore, onDropAfter: item.onDropAfter, onDragStarted: item.onDragStarted, onDragEndedAny: item.onDragEndedAny, feedbackSize: Size(_maxCrossAxisExtent * .65, _maxCrossAxisExtent * .65), ); } var _items = []; late double _maxCrossAxisExtent; }