Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add draggable/DragDelay option to ReorderableSliverList + all other widgets #181

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lib/reorderables.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ export 'src/widgets/reorderable_sliver.dart';
export 'src/widgets/reorderable_table.dart';
export 'src/widgets/reorderable_widget.dart';
export 'src/widgets/reorderable_wrap.dart';
export 'src/drag_delay_enum.dart';
1 change: 1 addition & 0 deletions lib/src/drag_delay_enum.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
enum DragDelay { short, long }
27 changes: 14 additions & 13 deletions lib/src/widgets/reorderable_flex.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import './passthrough_overlay.dart';
import './reorderable_mixin.dart';
import './reorderable_widget.dart';
import './typedefs.dart';
import '../drag_delay_enum.dart';

/// Reorderable (drag and drop) version of [Flex], a widget that displays its
/// draggable children in a one-dimensional array.
Expand All @@ -26,7 +27,7 @@ import './typedefs.dart';
/// top/left and bottom/right of the widget. If further control is needed, you
/// can use [buildItemsContainer] to customize how each item is contained, or
/// use [buildDraggableFeedback] to customize the [feedback] of the internal
/// [LongPressDraggable]. Consider using [ReorderableRow] or [ReorderableColumn]
/// [Draggable] widget. Consider using [ReorderableRow] or [ReorderableColumn]
/// instead using this widget directly.
///
/// All [children] must have a key.
Expand All @@ -52,7 +53,7 @@ class ReorderableFlex extends StatefulWidget {
this.onNoReorder,
this.onReorderStarted,
this.scrollController,
this.needsLongPressDraggable = true,
this.dragDelay = DragDelay.long,
this.draggingWidgetOpacity = 0.2,
this.reorderAnimationDuration,
this.scrollAnimationDuration,
Expand Down Expand Up @@ -102,7 +103,7 @@ class ReorderableFlex extends StatefulWidget {

final MainAxisAlignment mainAxisAlignment;

final bool needsLongPressDraggable;
final DragDelay dragDelay;
final double draggingWidgetOpacity;

final Duration? reorderAnimationDuration;
Expand Down Expand Up @@ -150,7 +151,7 @@ class _ReorderableFlexState extends State<ReorderableFlex> {
buildDraggableFeedback: widget.buildDraggableFeedback,
mainAxisAlignment: widget.mainAxisAlignment,
scrollController: widget.scrollController,
needsLongPressDraggable: widget.needsLongPressDraggable,
dragDelay: widget.dragDelay,
draggingWidgetOpacity: widget.draggingWidgetOpacity,
draggedItemBuilder: widget.draggedItemBuilder,
reorderAnimationDuration: widget.reorderAnimationDuration ??
Expand Down Expand Up @@ -189,7 +190,7 @@ class _ReorderableFlexContent extends StatefulWidget {
required this.onReorderStarted,
required this.mainAxisAlignment,
required this.scrollController,
required this.needsLongPressDraggable,
required this.dragDelay,
required this.draggingWidgetOpacity,
required this.buildItemsContainer,
required this.buildDraggableFeedback,
Expand All @@ -214,7 +215,7 @@ class _ReorderableFlexContent extends StatefulWidget {
final Widget Function(BuildContext context, int index)? draggedItemBuilder;

final MainAxisAlignment mainAxisAlignment;
final bool needsLongPressDraggable;
final DragDelay dragDelay;
final double draggingWidgetOpacity;
final Duration reorderAnimationDuration;
final Duration scrollAnimationDuration;
Expand Down Expand Up @@ -601,7 +602,7 @@ class _ReorderableFlexContentState extends State<_ReorderableFlexContent>
if (!isReorderable) {
child = toWrap;
} else {
child = widget.needsLongPressDraggable
child = widget.dragDelay == DragDelay.long
? LongPressDraggable<int>(
maxSimultaneousDrags: 1,
axis: widget.direction,
Expand Down Expand Up @@ -947,7 +948,7 @@ class _ReorderableFlexContentState extends State<_ReorderableFlexContent>
/// In addition to other parameters in [Row]'s constructor, this widget also
/// has [header] and [footer] for placing non-reorderable widgets at the top and
/// bottom of the widget, and [buildDraggableFeedback] to customize the
/// [feedback] widget of the internal [LongPressDraggable].
/// [feedback] widget of the internal [Draggable].
///
/// The [onReorder] function must be defined. A typical onReorder function looks
/// like the following:
Expand Down Expand Up @@ -984,7 +985,7 @@ class ReorderableRow extends ReorderableFlex {
NoReorderCallback? onNoReorder,
ReorderStartedCallback? onReorderStarted,
ScrollController? scrollController,
bool needsLongPressDraggable = true,
DragDelay dragDelay = DragDelay.long,
double draggingWidgetOpacity = 0.2,
Duration? reorderAnimationDuration,
Duration? scrollAnimationDuration,
Expand Down Expand Up @@ -1017,7 +1018,7 @@ class ReorderableRow extends ReorderableFlex {
buildDraggableFeedback: buildDraggableFeedback,
mainAxisAlignment: mainAxisAlignment,
scrollController: scrollController,
needsLongPressDraggable: needsLongPressDraggable,
dragDelay: dragDelay,
draggingWidgetOpacity: draggingWidgetOpacity,
reorderAnimationDuration: reorderAnimationDuration,
scrollAnimationDuration: scrollAnimationDuration,
Expand All @@ -1030,7 +1031,7 @@ class ReorderableRow extends ReorderableFlex {
/// In addition to other parameters in [Column]'s constructor, this widget also
/// has [header] and [footer] for placing non-reorderable widgets at the left and
/// right of the widget, and [buildDraggableFeedback] to customize the
/// [feedback] widget of the internal [LongPressDraggable].
/// [feedback] widget of the internal [Draggable].
///
/// The [onReorder] function must be defined. A typical onReorder function looks
/// like the following:
Expand Down Expand Up @@ -1067,7 +1068,7 @@ class ReorderableColumn extends ReorderableFlex {
NoReorderCallback? onNoReorder,
ReorderStartedCallback? onReorderStarted,
ScrollController? scrollController,
bool needsLongPressDraggable = true,
DragDelay dragDelay = DragDelay.long,
double draggingWidgetOpacity = 0.2,
Duration? reorderAnimationDuration,
Duration? scrollAnimationDuration,
Expand Down Expand Up @@ -1098,7 +1099,7 @@ class ReorderableColumn extends ReorderableFlex {
buildDraggableFeedback: buildDraggableFeedback,
mainAxisAlignment: mainAxisAlignment,
scrollController: scrollController,
needsLongPressDraggable: needsLongPressDraggable,
dragDelay: dragDelay,
draggingWidgetOpacity: draggingWidgetOpacity,
reorderAnimationDuration: reorderAnimationDuration,
scrollAnimationDuration: scrollAnimationDuration,
Expand Down
100 changes: 67 additions & 33 deletions lib/src/widgets/reorderable_sliver.dart
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,7 @@ class ReorderableSliverList extends StatefulWidget {
this.onReorderStarted,
this.onDragStart,
this.onDragEnd,
this.dragDelay = DragDelay.long,
this.enabled = true,
this.controller,
Key? key,
Expand Down Expand Up @@ -280,6 +281,9 @@ class ReorderableSliverList extends StatefulWidget {
final BuildItemsContainer? buildItemsContainer;
final BuildDraggableFeedback? buildDraggableFeedback;

// Sets the delay required to trigger dragging (short or long)
final DragDelay dragDelay;

/// Sets whether the children are reorderable or not
final bool enabled;

Expand Down Expand Up @@ -769,13 +773,14 @@ class _ReorderableSliverListState extends State<ReorderableSliverList>
} else {
// We build the draggable inside of a layout builder so that we can
// constrain the size of the feedback dragging widget.
child = LongPressDraggable<int>(
maxSimultaneousDrags: widget.enabled ? 1 : 0,
axis: Axis.vertical,
//widget.direction,
data: index,
//toWrap.key,
ignoringFeedbackSemantics: false,
child = widget.dragDelay == DragDelay.long
? LongPressDraggable<int>(
maxSimultaneousDrags: widget.enabled ? 1 : 0,
axis: Axis.vertical,
//widget.direction,
data: index,
//toWrap.key,
ignoringFeedbackSemantics: false,
// feedback: Container(
// alignment: Alignment.topLeft,
// // These constraints will limit the cross axis of the drawn widget.
Expand All @@ -785,7 +790,7 @@ class _ReorderableSliverListState extends State<ReorderableSliverList>
// child: IntrinsicWidth(child: toWrapWithSemantics),
// ),
// ),
feedback: feedbackBuilder,
feedback: feedbackBuilder,
// feedback: Transform(
// transform: new Matrix4.rotationZ(0),
// alignment: FractionalOffset.topLeft,
Expand All @@ -797,32 +802,61 @@ class _ReorderableSliverListState extends State<ReorderableSliverList>
// ),
// ),

// Wrap toWrapWithSemantics with a widget that supports HitTestBehavior
// to make sure the whole toWrapWithSemantics responds to pointer events, i.e. dragging
child: MetaData(
child: toWrapWithSemantics, behavior: HitTestBehavior.opaque),
//toWrapWithSemantics,//_dragging == toWrap.key ? const SizedBox() : toWrapWithSemantics,
childWhenDragging: IgnorePointer(
ignoring: true,
child: SizedBox(
// Small values (<50) cause an error when used with ListTile.
width: double.infinity,
child: Opacity(
opacity: 0,
// Wrap toWrapWithSemantics with a widget that supports HitTestBehavior
// to make sure the whole toWrapWithSemantics responds to pointer events, i.e. dragging
child: MetaData(
child: toWrapWithSemantics, behavior: HitTestBehavior.opaque),
//toWrapWithSemantics,//_dragging == toWrap.key ? const SizedBox() : toWrapWithSemantics,
childWhenDragging: IgnorePointer(
ignoring: true,
child: SizedBox(
// Small values (<50) cause an error when used with ListTile.
width: double.infinity,
child: Opacity(
opacity: 0,
// child: _makeAppearingWidget(toWrap)
child: Container(width: 0, height: 0, child: toWrap)))),
onDragStarted: onDragStarted,
dragAnchorStrategy: childDragAnchorStrategy,
// When the drag ends inside a DragTarget widget, the drag
// succeeds, and we reorder the widget into position appropriately.
onDragCompleted: onDragEnded,
// When the drag does not end inside a DragTarget widget, the
// drag fails, but we still reorder the widget to the last position it
// had been dragged to.
onDraggableCanceled: (Velocity velocity, Offset offset) {
onDragEnded();
},
);
child: Container(width: 0, height: 0, child: toWrap)))),
onDragStarted: onDragStarted,
dragAnchorStrategy: childDragAnchorStrategy,
// When the drag ends inside a DragTarget widget, the drag
// succeeds, and we reorder the widget into position appropriately.
onDragCompleted: onDragEnded,
// When the drag does not end inside a DragTarget widget, the
// drag fails, but we still reorder the widget to the last position it
// had been dragged to.
onDraggableCanceled: (Velocity velocity, Offset offset) {
onDragEnded();
},
)
: Draggable<int>(
maxSimultaneousDrags: widget.enabled ? 1 : 0,
axis: Axis.vertical,
data: index,
ignoringFeedbackSemantics: false,
feedback: feedbackBuilder,
child: MetaData(
child: toWrapWithSemantics,
behavior: HitTestBehavior.opaque),
childWhenDragging: IgnorePointer(
ignoring: true,
child: SizedBox(
// Small values (<50) cause an error when used with ListTile.
width: double.infinity,
child: Opacity(
opacity: 0,
child: Container(
width: 0, height: 0, child: toWrap)))),
onDragStarted: onDragStarted,
dragAnchorStrategy: childDragAnchorStrategy,
// When the drag ends inside a DragTarget widget, the drag
// succeeds, and we reorder the widget into position appropriately.
onDragCompleted: onDragEnded,
// When the drag does not end inside a DragTarget widget, the
// drag fails, but we still reorder the widget to the last position it
// had been dragged to.
onDraggableCanceled: (Velocity velocity, Offset offset) {
onDragEnded();
});
}

// The target for dropping at the end of the list doesn't need to be
Expand Down
7 changes: 4 additions & 3 deletions lib/src/widgets/reorderable_table.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import './reorderable_flex.dart';
import './tabluar_flex.dart';
import './typedefs.dart';
import '../rendering/tabluar_flex.dart';
import '../drag_delay_enum.dart';

class ReorderableTableRow extends TabluarRow {
ReorderableTableRow({
Expand Down Expand Up @@ -71,7 +72,7 @@ class ReorderableTable extends StatelessWidget {
this.reorderAnimationDuration,
this.scrollAnimationDuration,
this.ignorePrimaryScrollController = false,
this.needsLongPressDraggable = true,
this.dragDelay = DragDelay.long,
Key? key,
this.borderColor,
}) : assert(() {
Expand Down Expand Up @@ -175,7 +176,7 @@ class ReorderableTable extends StatelessWidget {
final Duration? scrollAnimationDuration;
final bool ignorePrimaryScrollController;

final bool needsLongPressDraggable;
final DragDelay dragDelay;

@override
Widget build(BuildContext context) {
Expand All @@ -196,7 +197,7 @@ class ReorderableTable extends StatelessWidget {
children: children,
onReorder: onReorder,
onNoReorder: onNoReorder,
needsLongPressDraggable: needsLongPressDraggable,
dragDelay: dragDelay,
direction: Axis.vertical,
buildItemsContainer: (BuildContext containerContext, Axis direction,
List<Widget> children) {
Expand Down
18 changes: 9 additions & 9 deletions lib/src/widgets/reorderable_wrap.dart
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class ReorderableWrap extends StatefulWidget {
this.padding,
this.buildItemsContainer,
this.buildDraggableFeedback,
this.needsLongPressDraggable = true,
this.dragDelay = DragDelay.long,
this.alignment = WrapAlignment.start,
this.spacing = 0.0,
this.runAlignment = WrapAlignment.start,
Expand Down Expand Up @@ -114,9 +114,9 @@ class ReorderableWrap extends StatefulWidget {
final BuildItemsContainer? buildItemsContainer;
final BuildDraggableFeedback? buildDraggableFeedback;

/// The flag of whether needs long press to trigger dragging mode.
/// true means it needs long press and false means no need.
final bool needsLongPressDraggable;
/// Enum flag used to determine if a long press or a short press is needed to
/// trigger dragging mode. DragDelay.long is the default
final DragDelay dragDelay;

/// How the children within a run should be places in the main axis.
///
Expand Down Expand Up @@ -289,7 +289,7 @@ class _ReorderableWrapState extends State<ReorderableWrap> {
padding: widget.padding,
buildItemsContainer: widget.buildItemsContainer,
buildDraggableFeedback: widget.buildDraggableFeedback,
needsLongPressDraggable: widget.needsLongPressDraggable,
dragDelay: widget.dragDelay,
alignment: widget.alignment,
spacing: widget.spacing,
runAlignment: widget.runAlignment,
Expand Down Expand Up @@ -335,7 +335,7 @@ class _ReorderableWrapContent extends StatefulWidget {
required this.onReorderStarted,
required this.buildItemsContainer,
required this.buildDraggableFeedback,
required this.needsLongPressDraggable,
required this.dragDelay,
required this.alignment,
required this.spacing,
required this.runAlignment,
Expand All @@ -352,7 +352,7 @@ class _ReorderableWrapContent extends StatefulWidget {
this.scrollAnimationDuration = const Duration(milliseconds: 200),
required this.enableReorder
});

final List<Widget>? header;
final Widget? footer;
final ScrollController? controller;
Expand All @@ -366,7 +366,7 @@ class _ReorderableWrapContent extends StatefulWidget {
final ReorderStartedCallback? onReorderStarted;
final BuildItemsContainer? buildItemsContainer;
final BuildDraggableFeedback? buildDraggableFeedback;
final bool needsLongPressDraggable;
final DragDelay dragDelay;

final WrapAlignment alignment;
final double spacing;
Expand Down Expand Up @@ -826,7 +826,7 @@ class _ReorderableWrapContentState extends State<_ReorderableWrapContent>
} else {
// We build the draggable inside of a layout builder so that we can
// constrain the size of the feedback dragging widget.
child = this.widget.needsLongPressDraggable
child = this.widget.dragDelay == DragDelay.long
? LongPressDraggable<int>(
maxSimultaneousDrags: 1,
data: index,
Expand Down