Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
5159ab35
Unverified
Commit
5159ab35
authored
May 15, 2018
by
David Shuckerow
Committed by
GitHub
May 15, 2018
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add the ability to limit Draggables to a single axis (#17587)
* Add a draggable axis restrictor and tests
parent
c4cb0ecf
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
173 additions
and
3 deletions
+173
-3
drag_target.dart
packages/flutter/lib/src/widgets/drag_target.dart
+45
-3
draggable_test.dart
packages/flutter/test/widgets/draggable_test.dart
+128
-0
No files found.
packages/flutter/lib/src/widgets/drag_target.dart
View file @
5159ab35
...
...
@@ -92,6 +92,7 @@ class Draggable<T> extends StatefulWidget {
@required
this
.
child
,
@required
this
.
feedback
,
this
.
data
,
this
.
axis
,
this
.
childWhenDragging
,
this
.
feedbackOffset
:
Offset
.
zero
,
this
.
dragAnchor
:
DragAnchor
.
child
,
...
...
@@ -109,6 +110,19 @@ class Draggable<T> extends StatefulWidget {
/// The data that will be dropped by this draggable.
final
T
data
;
/// The [Axis] to restrict this draggable's movement, if specified.
///
/// When axis is set to [Axis.horizontal], this widget can only be dragged
/// horizontally. Behavior is similar for [Axis.vertical].
///
/// Defaults to allowing drag on both [Axis.horizontal] and [Axis.vertical].
///
/// When null, allows drag on both [Axis.horizontal] and [Axis.vertical].
///
/// For the direction of gestures this widget competes with to start a drag
/// event, see [Draggable.affinity].
final
Axis
axis
;
/// The widget below this widget in the tree.
///
/// This widget displays [child] when zero drags are under way. If
...
...
@@ -164,6 +178,9 @@ class Draggable<T> extends StatefulWidget {
/// affinity, pointer motion in any direction will result in a drag rather
/// than in a scroll because the draggable widget, being the more specific
/// widget, will out-compete the [Scrollable] for vertical gestures.
///
/// For the directions this widget can be dragged in after the drag event
/// starts, see [Draggable.axis].
final
Axis
affinity
;
/// How many simultaneous drags to support.
...
...
@@ -229,6 +246,7 @@ class LongPressDraggable<T> extends Draggable<T> {
@required
Widget
child
,
@required
Widget
feedback
,
T
data
,
Axis
axis
,
Widget
childWhenDragging
,
Offset
feedbackOffset:
Offset
.
zero
,
DragAnchor
dragAnchor:
DragAnchor
.
child
,
...
...
@@ -241,6 +259,7 @@ class LongPressDraggable<T> extends Draggable<T> {
child:
child
,
feedback:
feedback
,
data:
data
,
axis:
axis
,
childWhenDragging:
childWhenDragging
,
feedbackOffset:
feedbackOffset
,
dragAnchor:
dragAnchor
,
...
...
@@ -311,7 +330,7 @@ class _DraggableState<T> extends State<Draggable<T>> {
break
;
case
DragAnchor
.
pointer
:
dragStartPoint
=
Offset
.
zero
;
break
;
break
;
}
setState
(()
{
_activeCount
+=
1
;
...
...
@@ -319,6 +338,7 @@ class _DraggableState<T> extends State<Draggable<T>> {
final
_DragAvatar
<
T
>
avatar
=
new
_DragAvatar
<
T
>(
overlayState:
Overlay
.
of
(
context
,
debugRequiredFor:
widget
),
data:
widget
.
data
,
axis:
widget
.
axis
,
initialPosition:
position
,
dragStartPoint:
dragStartPoint
,
feedback:
widget
.
feedback
,
...
...
@@ -471,6 +491,7 @@ class _DragAvatar<T> extends Drag {
_DragAvatar
({
@required
this
.
overlayState
,
this
.
data
,
this
.
axis
,
Offset
initialPosition
,
this
.
dragStartPoint
:
Offset
.
zero
,
this
.
feedback
,
...
...
@@ -486,6 +507,7 @@ class _DragAvatar<T> extends Drag {
}
final
T
data
;
final
Axis
axis
;
final
Offset
dragStartPoint
;
final
Widget
feedback
;
final
Offset
feedbackOffset
;
...
...
@@ -500,15 +522,16 @@ class _DragAvatar<T> extends Drag {
@override
void
update
(
DragUpdateDetails
details
)
{
_position
+=
details
.
delta
;
_position
+=
_restrictAxis
(
details
.
delta
)
;
updateDrag
(
_position
);
}
@override
void
end
(
DragEndDetails
details
)
{
finishDrag
(
_DragEndKind
.
dropped
,
details
.
velocity
);
finishDrag
(
_DragEndKind
.
dropped
,
_restrictVelocityAxis
(
details
.
velocity
)
);
}
@override
void
cancel
()
{
finishDrag
(
_DragEndKind
.
canceled
);
...
...
@@ -600,4 +623,23 @@ class _DragAvatar<T> extends Drag {
)
);
}
Velocity
_restrictVelocityAxis
(
Velocity
velocity
)
{
if
(
axis
==
null
)
{
return
velocity
;
}
return
new
Velocity
(
pixelsPerSecond:
_restrictAxis
(
velocity
.
pixelsPerSecond
),
);
}
Offset
_restrictAxis
(
Offset
offset
)
{
if
(
axis
==
null
)
{
return
offset
;
}
if
(
axis
==
Axis
.
horizontal
)
{
return
new
Offset
(
offset
.
dx
,
0.0
);
}
return
new
Offset
(
0.0
,
offset
.
dy
);
}
}
packages/flutter/test/widgets/draggable_test.dart
View file @
5159ab35
...
...
@@ -586,6 +586,134 @@ void main() {
events
.
clear
();
});
group
(
'Drag and drop - Draggables with a set axis only move along that axis'
,
()
{
final
List
<
String
>
events
=
<
String
>[];
Widget
build
()
{
return
new
MaterialApp
(
home:
new
ListView
(
scrollDirection:
Axis
.
horizontal
,
children:
<
Widget
>[
new
DragTarget
<
int
>(
builder:
(
BuildContext
context
,
List
<
int
>
data
,
List
<
dynamic
>
rejects
)
{
return
const
Text
(
'Target'
);
},
onAccept:
(
int
data
)
{
events
.
add
(
'drop
$data
'
);
}
),
new
Container
(
width:
400.0
),
const
Draggable
<
int
>(
data:
1
,
child:
const
Text
(
'H'
),
feedback:
const
Text
(
'H'
),
childWhenDragging:
const
SizedBox
(),
axis:
Axis
.
horizontal
,
),
const
Draggable
<
int
>(
data:
2
,
child:
const
Text
(
'V'
),
feedback:
const
Text
(
'V'
),
childWhenDragging:
const
SizedBox
(),
axis:
Axis
.
vertical
,
),
const
Draggable
<
int
>(
data:
3
,
child:
const
Text
(
'N'
),
feedback:
const
Text
(
'N'
),
childWhenDragging:
const
SizedBox
(),
),
new
Container
(
width:
500.0
),
new
Container
(
width:
500.0
),
new
Container
(
width:
500.0
),
new
Container
(
width:
500.0
),
],
),
);
}
testWidgets
(
'Null axis draggable moves along all axes'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
build
());
final
Offset
firstLocation
=
tester
.
getTopLeft
(
find
.
text
(
'N'
));
final
Offset
secondLocation
=
firstLocation
+
const
Offset
(
300.0
,
300.0
);
final
Offset
thirdLocation
=
firstLocation
+
const
Offset
(-
300.0
,
-
300.0
);
final
TestGesture
gesture
=
await
tester
.
startGesture
(
firstLocation
,
pointer:
7
);
await
tester
.
pump
();
await
gesture
.
moveTo
(
secondLocation
);
await
tester
.
pump
();
expect
(
tester
.
getTopLeft
(
find
.
text
(
'N'
)),
secondLocation
);
await
gesture
.
moveTo
(
thirdLocation
);
await
tester
.
pump
();
expect
(
tester
.
getTopLeft
(
find
.
text
(
'N'
)),
thirdLocation
);
});
testWidgets
(
'Horizontal axis draggable moves horizontally'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
build
());
final
Offset
firstLocation
=
tester
.
getTopLeft
(
find
.
text
(
'H'
));
final
Offset
secondLocation
=
firstLocation
+
const
Offset
(
300.0
,
0.0
);
final
Offset
thirdLocation
=
firstLocation
+
const
Offset
(-
300.0
,
0.0
);
final
TestGesture
gesture
=
await
tester
.
startGesture
(
firstLocation
,
pointer:
7
);
await
tester
.
pump
();
await
gesture
.
moveTo
(
secondLocation
);
await
tester
.
pump
();
expect
(
tester
.
getTopLeft
(
find
.
text
(
'H'
)),
secondLocation
);
await
gesture
.
moveTo
(
thirdLocation
);
await
tester
.
pump
();
expect
(
tester
.
getTopLeft
(
find
.
text
(
'H'
)),
thirdLocation
);
});
testWidgets
(
'Horizontal axis draggable does not move vertically'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
build
());
final
Offset
firstLocation
=
tester
.
getTopLeft
(
find
.
text
(
'H'
));
final
Offset
secondDragLocation
=
firstLocation
+
const
Offset
(
300.0
,
200.0
);
// The horizontal drag widget won't scroll vertically.
final
Offset
secondWidgetLocation
=
firstLocation
+
const
Offset
(
300.0
,
0.0
);
final
Offset
thirdDragLocation
=
firstLocation
+
const
Offset
(-
300.0
,
-
200.0
);
final
Offset
thirdWidgetLocation
=
firstLocation
+
const
Offset
(-
300.0
,
0.0
);
final
TestGesture
gesture
=
await
tester
.
startGesture
(
firstLocation
,
pointer:
7
);
await
tester
.
pump
();
await
gesture
.
moveTo
(
secondDragLocation
);
await
tester
.
pump
();
expect
(
tester
.
getTopLeft
(
find
.
text
(
'H'
)),
secondWidgetLocation
);
await
gesture
.
moveTo
(
thirdDragLocation
);
await
tester
.
pump
();
expect
(
tester
.
getTopLeft
(
find
.
text
(
'H'
)),
thirdWidgetLocation
);
});
testWidgets
(
'Vertical axis draggable moves vertically'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
build
());
final
Offset
firstLocation
=
tester
.
getTopLeft
(
find
.
text
(
'V'
));
final
Offset
secondLocation
=
firstLocation
+
const
Offset
(
0.0
,
300.0
);
final
Offset
thirdLocation
=
firstLocation
+
const
Offset
(
0.0
,
-
300.0
);
final
TestGesture
gesture
=
await
tester
.
startGesture
(
firstLocation
,
pointer:
7
);
await
tester
.
pump
();
await
gesture
.
moveTo
(
secondLocation
);
await
tester
.
pump
();
expect
(
tester
.
getTopLeft
(
find
.
text
(
'V'
)),
secondLocation
);
await
gesture
.
moveTo
(
thirdLocation
);
await
tester
.
pump
();
expect
(
tester
.
getTopLeft
(
find
.
text
(
'V'
)),
thirdLocation
);
});
testWidgets
(
'Vertical axis draggable does not move horizontally'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
build
());
final
Offset
firstLocation
=
tester
.
getTopLeft
(
find
.
text
(
'V'
));
final
Offset
secondDragLocation
=
firstLocation
+
const
Offset
(
200.0
,
300.0
);
// The vertical drag widget won't scroll horizontally.
final
Offset
secondWidgetLocation
=
firstLocation
+
const
Offset
(
0.0
,
300.0
);
final
Offset
thirdDragLocation
=
firstLocation
+
const
Offset
(-
200.0
,
-
300.0
);
final
Offset
thirdWidgetLocation
=
firstLocation
+
const
Offset
(
0.0
,
-
300.0
);
final
TestGesture
gesture
=
await
tester
.
startGesture
(
firstLocation
,
pointer:
7
);
await
tester
.
pump
();
await
gesture
.
moveTo
(
secondDragLocation
);
await
tester
.
pump
();
expect
(
tester
.
getTopLeft
(
find
.
text
(
'V'
)),
secondWidgetLocation
);
await
gesture
.
moveTo
(
thirdDragLocation
);
await
tester
.
pump
();
expect
(
tester
.
getTopLeft
(
find
.
text
(
'V'
)),
thirdWidgetLocation
);
});
});
testWidgets
(
'Drag and drop - onDraggableCanceled not called if dropped on accepting target'
,
(
WidgetTester
tester
)
async
{
final
List
<
int
>
accepted
=
<
int
>[];
bool
onDraggableCanceledCalled
=
false
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment