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
30cc01fb
Unverified
Commit
30cc01fb
authored
Oct 15, 2021
by
Bonsai11
Committed by
GitHub
Oct 15, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add callback when dismiss threshold is reached (#88736)
parent
ab5dfe1d
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
110 additions
and
1 deletion
+110
-1
dismissible.dart
packages/flutter/lib/src/widgets/dismissible.dart
+56
-1
dismissible_test.dart
packages/flutter/test/widgets/dismissible_test.dart
+54
-0
No files found.
packages/flutter/lib/src/widgets/dismissible.dart
View file @
30cc01fb
...
@@ -30,6 +30,11 @@ typedef DismissDirectionCallback = void Function(DismissDirection direction);
...
@@ -30,6 +30,11 @@ typedef DismissDirectionCallback = void Function(DismissDirection direction);
/// Used by [Dismissible.confirmDismiss].
/// Used by [Dismissible.confirmDismiss].
typedef
ConfirmDismissCallback
=
Future
<
bool
?>
Function
(
DismissDirection
direction
);
typedef
ConfirmDismissCallback
=
Future
<
bool
?>
Function
(
DismissDirection
direction
);
/// Signature used by [Dismissible] to indicate that the dismissible has been dragged.
///
/// Used by [Dismissible.onUpdate].
typedef
DismissUpdateCallback
=
void
Function
(
DismissUpdateDetails
details
);
/// The direction in which a [Dismissible] can be dismissed.
/// The direction in which a [Dismissible] can be dismissed.
enum
DismissDirection
{
enum
DismissDirection
{
/// The [Dismissible] can be dismissed by dragging either up or down.
/// The [Dismissible] can be dismissed by dragging either up or down.
...
@@ -98,6 +103,7 @@ class Dismissible extends StatefulWidget {
...
@@ -98,6 +103,7 @@ class Dismissible extends StatefulWidget {
this
.
secondaryBackground
,
this
.
secondaryBackground
,
this
.
confirmDismiss
,
this
.
confirmDismiss
,
this
.
onResize
,
this
.
onResize
,
this
.
onUpdate
,
this
.
onDismissed
,
this
.
onDismissed
,
this
.
direction
=
DismissDirection
.
horizontal
,
this
.
direction
=
DismissDirection
.
horizontal
,
this
.
resizeDuration
=
const
Duration
(
milliseconds:
300
),
this
.
resizeDuration
=
const
Duration
(
milliseconds:
300
),
...
@@ -205,10 +211,44 @@ class Dismissible extends StatefulWidget {
...
@@ -205,10 +211,44 @@ class Dismissible extends StatefulWidget {
/// This defaults to [HitTestBehavior.opaque].
/// This defaults to [HitTestBehavior.opaque].
final
HitTestBehavior
behavior
;
final
HitTestBehavior
behavior
;
/// Called when the dismissible widget has been dragged.
///
/// If [onUpdate] is not null, then it will be invoked for every pointer event
/// to dispatch the latest state of the drag. For example, this callback
/// can be used to for example change the color of the background widget
/// depending on whether the dismiss threshold is currently reached.
final
DismissUpdateCallback
?
onUpdate
;
@override
@override
State
<
Dismissible
>
createState
()
=>
_DismissibleState
();
State
<
Dismissible
>
createState
()
=>
_DismissibleState
();
}
}
/// Details for [DismissUpdateCallback].
///
/// See also:
///
/// * [Dismissible.onUpdate], which receives this information.
class
DismissUpdateDetails
{
/// Create a new instance of [DismissUpdateDetails].
DismissUpdateDetails
({
this
.
direction
=
DismissDirection
.
horizontal
,
this
.
reached
=
false
,
this
.
previousReached
=
false
});
/// The direction that the dismissible is being dragged.
final
DismissDirection
direction
;
/// Whether the dismiss threshold is currently reached.
final
bool
reached
;
/// Whether the dismiss threshold was reached the last time this callback was invoked.
///
/// This can be used in conjunction with [DismissUpdateDetails.reached] to catch the moment
/// that the [Dismissible] is dragged across the threshold.
final
bool
previousReached
;
}
class
_DismissibleClipper
extends
CustomClipper
<
Rect
>
{
class
_DismissibleClipper
extends
CustomClipper
<
Rect
>
{
_DismissibleClipper
({
_DismissibleClipper
({
required
this
.
axis
,
required
this
.
axis
,
...
@@ -254,7 +294,8 @@ class _DismissibleState extends State<Dismissible> with TickerProviderStateMixin
...
@@ -254,7 +294,8 @@ class _DismissibleState extends State<Dismissible> with TickerProviderStateMixin
void
initState
()
{
void
initState
()
{
super
.
initState
();
super
.
initState
();
_moveController
=
AnimationController
(
duration:
widget
.
movementDuration
,
vsync:
this
)
_moveController
=
AnimationController
(
duration:
widget
.
movementDuration
,
vsync:
this
)
..
addStatusListener
(
_handleDismissStatusChanged
);
..
addStatusListener
(
_handleDismissStatusChanged
)
..
addListener
(
_handleDismissUpdateValueChanged
);
_updateMoveAnimation
();
_updateMoveAnimation
();
}
}
...
@@ -268,6 +309,7 @@ class _DismissibleState extends State<Dismissible> with TickerProviderStateMixin
...
@@ -268,6 +309,7 @@ class _DismissibleState extends State<Dismissible> with TickerProviderStateMixin
bool
_confirming
=
false
;
bool
_confirming
=
false
;
bool
_dragUnderway
=
false
;
bool
_dragUnderway
=
false
;
Size
?
_sizePriorToCollapse
;
Size
?
_sizePriorToCollapse
;
bool
_dismissThresholdReached
=
false
;
@override
@override
bool
get
wantKeepAlive
=>
_moveController
?.
isAnimating
==
true
||
_resizeController
?.
isAnimating
==
true
;
bool
get
wantKeepAlive
=>
_moveController
?.
isAnimating
==
true
||
_resizeController
?.
isAnimating
==
true
;
...
@@ -388,6 +430,19 @@ class _DismissibleState extends State<Dismissible> with TickerProviderStateMixin
...
@@ -388,6 +430,19 @@ class _DismissibleState extends State<Dismissible> with TickerProviderStateMixin
}
}
}
}
void
_handleDismissUpdateValueChanged
()
{
if
(
widget
.
onUpdate
!=
null
)
{
final
bool
oldDismissThresholdReached
=
_dismissThresholdReached
;
_dismissThresholdReached
=
_moveController
!.
value
>
(
widget
.
dismissThresholds
[
_dismissDirection
]
??
_kDismissThreshold
);
final
DismissUpdateDetails
details
=
DismissUpdateDetails
(
direction:
_dismissDirection
,
reached:
_dismissThresholdReached
,
previousReached:
oldDismissThresholdReached
,
);
widget
.
onUpdate
!(
details
);
}
}
void
_updateMoveAnimation
()
{
void
_updateMoveAnimation
()
{
final
double
end
=
_dragExtent
.
sign
;
final
double
end
=
_dragExtent
.
sign
;
_moveAnimation
=
_moveController
!.
drive
(
_moveAnimation
=
_moveController
!.
drive
(
...
...
packages/flutter/test/widgets/dismissible_test.dart
View file @
30cc01fb
...
@@ -10,6 +10,9 @@ import 'package:flutter_test/flutter_test.dart';
...
@@ -10,6 +10,9 @@ import 'package:flutter_test/flutter_test.dart';
const
DismissDirection
defaultDismissDirection
=
DismissDirection
.
horizontal
;
const
DismissDirection
defaultDismissDirection
=
DismissDirection
.
horizontal
;
const
double
crossAxisEndOffset
=
0.5
;
const
double
crossAxisEndOffset
=
0.5
;
bool
reportedDismissUpdateReached
=
false
;
bool
reportedDismissUpdatePreviousReached
=
false
;
late
DismissDirection
reportedDismissUpdateReachedDirection
;
DismissDirection
reportedDismissDirection
=
DismissDirection
.
horizontal
;
DismissDirection
reportedDismissDirection
=
DismissDirection
.
horizontal
;
List
<
int
>
dismissedItems
=
<
int
>[];
List
<
int
>
dismissedItems
=
<
int
>[];
...
@@ -46,6 +49,11 @@ Widget buildTest({
...
@@ -46,6 +49,11 @@ Widget buildTest({
onResize:
()
{
onResize:
()
{
expect
(
dismissedItems
.
contains
(
item
),
isFalse
);
expect
(
dismissedItems
.
contains
(
item
),
isFalse
);
},
},
onUpdate:
(
DismissUpdateDetails
details
)
{
reportedDismissUpdateReachedDirection
=
details
.
direction
;
reportedDismissUpdateReached
=
details
.
reached
;
reportedDismissUpdatePreviousReached
=
details
.
previousReached
;
},
background:
background
,
background:
background
,
dismissThresholds:
startToEndThreshold
==
null
dismissThresholds:
startToEndThreshold
==
null
?
<
DismissDirection
,
double
>{}
?
<
DismissDirection
,
double
>{}
...
@@ -1053,4 +1061,50 @@ void main() {
...
@@ -1053,4 +1061,50 @@ void main() {
expect
(
controller
.
offset
,
100.0
);
expect
(
controller
.
offset
,
100.0
);
controller
.
dispose
();
controller
.
dispose
();
});
});
testWidgets
(
'onUpdate'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
buildTest
(
scrollDirection:
Axis
.
horizontal
,
));
expect
(
dismissedItems
,
isEmpty
);
// Successful dismiss therefore threshold has been reached
await
dismissItem
(
tester
,
0
,
mechanism:
flingElement
,
gestureDirection:
AxisDirection
.
left
);
expect
(
find
.
text
(
'0'
),
findsNothing
);
expect
(
dismissedItems
,
equals
(<
int
>[
0
]));
expect
(
reportedDismissUpdateReachedDirection
,
DismissDirection
.
endToStart
);
expect
(
reportedDismissUpdateReached
,
true
);
expect
(
reportedDismissUpdatePreviousReached
,
true
);
// Unsuccessful dismiss, threshold has not been reached
await
checkFlingItemAfterMovement
(
tester
,
1
,
gestureDirection:
AxisDirection
.
right
);
expect
(
find
.
text
(
'1'
),
findsOneWidget
);
expect
(
dismissedItems
,
equals
(<
int
>[
0
]));
expect
(
reportedDismissUpdateReachedDirection
,
DismissDirection
.
startToEnd
);
expect
(
reportedDismissUpdateReached
,
false
);
expect
(
reportedDismissUpdatePreviousReached
,
false
);
// Another successful dismiss from another direction
await
dismissItem
(
tester
,
1
,
mechanism:
flingElement
,
gestureDirection:
AxisDirection
.
right
);
expect
(
find
.
text
(
'1'
),
findsNothing
);
expect
(
dismissedItems
,
equals
(<
int
>[
0
,
1
]));
expect
(
reportedDismissUpdateReachedDirection
,
DismissDirection
.
startToEnd
);
expect
(
reportedDismissUpdateReached
,
true
);
expect
(
reportedDismissUpdatePreviousReached
,
true
);
await
tester
.
pumpWidget
(
buildTest
(
scrollDirection:
Axis
.
horizontal
,
confirmDismiss:
(
BuildContext
context
,
DismissDirection
dismissDirection
)
{
return
Future
<
bool
>.
value
(
false
);
},
));
// Threshold has been reached but dismiss was not confirmed
await
dismissItem
(
tester
,
2
,
mechanism:
flingElement
,
gestureDirection:
AxisDirection
.
right
);
expect
(
find
.
text
(
'2'
),
findsOneWidget
);
expect
(
dismissedItems
,
equals
(<
int
>[
0
,
1
]));
expect
(
reportedDismissUpdateReachedDirection
,
DismissDirection
.
startToEnd
);
expect
(
reportedDismissUpdateReached
,
false
);
expect
(
reportedDismissUpdatePreviousReached
,
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