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
34f69cea
Unverified
Commit
34f69cea
authored
Jul 17, 2021
by
Max
Committed by
GitHub
Jul 17, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add AnimatedSlide widget (#86395)
parent
b217575c
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
189 additions
and
1 deletion
+189
-1
implicit_animations.dart
packages/flutter/lib/src/widgets/implicit_animations.dart
+119
-1
implicit_animations_test.dart
packages/flutter/test/widgets/implicit_animations_test.dart
+70
-0
No files found.
packages/flutter/lib/src/widgets/implicit_animations.dart
View file @
34f69cea
...
...
@@ -257,6 +257,7 @@ class TextStyleTween extends Tween<TextStyle> {
/// [DefaultTextStyle].
/// * [AnimatedScale], which is an implicitly animated version of [Transform.scale].
/// * [AnimatedRotation], which is an implicitly animated version of [Transform.rotate].
/// * [AnimatedSlide], which implicitly animates the position of a widget relative to its normal position.
/// * [AnimatedOpacity], which is an implicitly animated version of [Opacity].
/// * [AnimatedPadding], which is an implicitly animated version of [Padding].
/// * [AnimatedPhysicalModel], which is an implicitly animated version of
...
...
@@ -616,7 +617,7 @@ abstract class AnimatedWidgetBaseState<T extends ImplicitlyAnimatedWidget> exten
/// transitions its child's position over a given duration whenever the given
/// position changes.
/// * [AnimatedAlign], which automatically transitions its child's
/// position over a given duration whenever the given [alignment] changes.
/// position over a given duration whenever the given [
AnimatedAlign.
alignment] changes.
/// * [AnimatedSwitcher], which switches out a child for a new one with a customizable transition.
/// * [AnimatedCrossFade], which fades between two children and interpolates their sizes.
class
AnimatedContainer
extends
ImplicitlyAnimatedWidget
{
...
...
@@ -973,6 +974,7 @@ class _AnimatedPaddingState extends AnimatedWidgetBaseState<AnimatedPadding> {
/// * [AnimatedContainer], which can transition more values at once.
/// * [AnimatedPadding], which can animate the padding instead of the
/// alignment.
/// * [AnimatedSlide], which can animate the translation of child by a given offset relative to its size.
/// * [AnimatedPositioned], which, as a child of a [Stack], automatically
/// transitions its child's position over a given duration whenever the given
/// position changes.
...
...
@@ -1464,6 +1466,7 @@ class _AnimatedPositionedDirectionalState extends AnimatedWidgetBaseState<Animat
/// * [AnimatedRotation], for animating the rotation of a child.
/// * [AnimatedSize], for animating the resize of a child based on changes
/// in layout.
/// * [AnimatedSlide], for animating the translation of a child by a given offset relative to its size.
/// * [ScaleTransition], an explicitly animated version of this widget, where
/// an [Animation] is provided by the caller instead of being built in.
class
AnimatedScale
extends
ImplicitlyAnimatedWidget
{
...
...
@@ -1671,6 +1674,121 @@ class _AnimatedRotationState extends ImplicitlyAnimatedWidgetState<AnimatedRotat
}
}
/// Widget which automatically transitions the child's
/// offset relative to its normal position whenever the given offset changes.
///
/// The translation is expressed as an [Offset] scaled to the child's size. For
/// example, an [Offset] with a `dx` of 0.25 will result in a horizontal
/// translation of one quarter the width of the child.
///
/// {@tool dartpad --template=stateful_widget_scaffold}
///
/// This code defines a widget that uses [AnimatedSlide] to translate a [FlutterLogo]
/// up or down by the amount of it's height with each press of the corresponding button.
///
/// ```dart
/// Offset offset = Offset.zero;
///
/// void _slideUp() {
/// setState(() => offset -= const Offset(0, 1));
/// }
///
/// void _slideDown() {
/// setState(() => offset += const Offset(0, 1));
/// }
///
/// @override
/// Widget build(BuildContext context) {
/// return Column(
/// mainAxisSize: MainAxisSize.min,
/// children: <Widget>[
/// ElevatedButton(
/// child: const Text('Slide up'),
/// onPressed: _slideUp,
/// ),
/// ElevatedButton(
/// child: const Text('Slide down'),
/// onPressed: _slideDown,
/// ),
/// Padding(
/// padding: const EdgeInsets.all(50),
/// child: AnimatedSlide(
/// offset: offset,
/// duration: const Duration(milliseconds: 500),
/// curve: Curves.easeInOut,
/// child: const FlutterLogo(),
/// ),
/// ),
/// ],
/// );
/// }
/// ```
/// {@end-tool}
///
/// See also:
///
/// * [AnimatedPositioned], which, as a child of a [Stack], automatically
/// transitions its child's position over a given duration whenever the given
/// position changes.
/// * [AnimatedAlign], which automatically transitions its child's
/// position over a given duration whenever the given [AnimatedAlign.alignment] changes.
class
AnimatedSlide
extends
ImplicitlyAnimatedWidget
{
/// Creates a widget that animates its offset translation implicitly.
///
/// The [offset] and [duration] arguments must not be null.
const
AnimatedSlide
({
Key
?
key
,
this
.
child
,
required
this
.
offset
,
Curve
curve
=
Curves
.
linear
,
required
Duration
duration
,
VoidCallback
?
onEnd
,
})
:
super
(
key:
key
,
curve:
curve
,
duration:
duration
,
onEnd:
onEnd
);
/// The widget below this widget in the tree.
///
/// {@macro flutter.widgets.ProxyWidget.child}
final
Widget
?
child
;
/// The target offset.
/// The child will be translated horizontally by `width * dx` and vertically by `height * dy`
///
/// The offset must not be null.
final
Offset
offset
;
@override
ImplicitlyAnimatedWidgetState
<
AnimatedSlide
>
createState
()
=>
_AnimatedSlideState
();
@override
void
debugFillProperties
(
DiagnosticPropertiesBuilder
properties
)
{
super
.
debugFillProperties
(
properties
);
properties
.
add
(
DiagnosticsProperty
<
Offset
>(
'offset'
,
offset
));
}
}
class
_AnimatedSlideState
extends
ImplicitlyAnimatedWidgetState
<
AnimatedSlide
>
{
Tween
<
Offset
>?
_offset
;
late
Animation
<
Offset
>
_offsetAnimation
;
@override
void
forEachTween
(
TweenVisitor
<
dynamic
>
visitor
)
{
_offset
=
visitor
(
_offset
,
widget
.
offset
,
(
dynamic
value
)
=>
Tween
<
Offset
>(
begin:
value
as
Offset
))
as
Tween
<
Offset
>?;
}
@override
void
didUpdateTweens
()
{
_offsetAnimation
=
animation
.
drive
(
_offset
!);
}
@override
Widget
build
(
BuildContext
context
)
{
return
SlideTransition
(
position:
_offsetAnimation
,
child:
widget
.
child
,
);
}
}
/// Animated version of [Opacity] which automatically transitions the child's
/// opacity over a given duration whenever the given opacity changes.
///
...
...
packages/flutter/test/widgets/implicit_animations_test.dart
View file @
34f69cea
...
...
@@ -171,6 +171,64 @@ void main() {
expect
(
mockOnEndFunction
.
called
,
1
);
});
testWidgets
(
'AnimatedSlide onEnd callback test'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
wrap
(
child:
TestAnimatedWidget
(
callback:
mockOnEndFunction
.
handler
,
switchKey:
switchKey
,
state:
_TestAnimatedSlideWidgetState
(),
),
));
final
Finder
widgetFinder
=
find
.
byKey
(
switchKey
);
await
tester
.
tap
(
widgetFinder
);
await
tester
.
pump
();
expect
(
mockOnEndFunction
.
called
,
0
);
await
tester
.
pump
(
animationDuration
);
expect
(
mockOnEndFunction
.
called
,
0
);
await
tester
.
pump
(
additionalDelay
);
expect
(
mockOnEndFunction
.
called
,
1
);
});
testWidgets
(
'AnimatedSlide transition test'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
wrap
(
child:
TestAnimatedWidget
(
switchKey:
switchKey
,
state:
_TestAnimatedSlideWidgetState
(),
),
));
final
RebuildCountingState
<
StatefulWidget
>
state
=
tester
.
widget
<
TestAnimatedWidget
>(
find
.
byType
(
TestAnimatedWidget
)
).
rebuildState
!;
final
Finder
switchFinder
=
find
.
byKey
(
switchKey
);
final
SlideTransition
slideWidget
=
tester
.
widget
<
SlideTransition
>(
find
.
ancestor
(
of:
find
.
byType
(
Placeholder
),
matching:
find
.
byType
(
SlideTransition
),
).
first
,
);
expect
(
state
.
builds
,
equals
(
1
));
await
tester
.
tap
(
switchFinder
);
expect
(
state
.
builds
,
equals
(
1
));
await
tester
.
pump
();
expect
(
slideWidget
.
position
.
value
,
equals
(
Offset
.
zero
));
expect
(
state
.
builds
,
equals
(
2
));
await
tester
.
pump
(
const
Duration
(
milliseconds:
500
));
expect
(
slideWidget
.
position
.
value
,
equals
(
const
Offset
(
0.5
,
0.5
)));
expect
(
state
.
builds
,
equals
(
2
));
await
tester
.
pump
(
const
Duration
(
milliseconds:
250
));
expect
(
slideWidget
.
position
.
value
,
equals
(
const
Offset
(
0.75
,
0.75
)));
expect
(
state
.
builds
,
equals
(
2
));
await
tester
.
pump
(
const
Duration
(
milliseconds:
250
));
expect
(
slideWidget
.
position
.
value
,
equals
(
const
Offset
(
1
,
1
)));
expect
(
state
.
builds
,
equals
(
2
));
});
testWidgets
(
'AnimatedScale onEnd callback test'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
wrap
(
child:
TestAnimatedWidget
(
...
...
@@ -660,6 +718,18 @@ class _TestAnimatedPositionedDirectionalWidgetState extends _TestAnimatedWidgetS
}
}
class
_TestAnimatedSlideWidgetState
extends
_TestAnimatedWidgetState
{
@override
Widget
getAnimatedWidget
()
{
return
AnimatedSlide
(
duration:
duration
,
onEnd:
widget
.
callback
,
offset:
toggle
?
const
Offset
(
1
,
1
)
:
Offset
.
zero
,
child:
child
,
);
}
}
class
_TestAnimatedScaleWidgetState
extends
_TestAnimatedWidgetState
{
@override
Widget
getAnimatedWidget
()
{
...
...
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