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
5ca4cc88
Commit
5ca4cc88
authored
Jan 14, 2020
by
Kate Lovett
Committed by
Flutter GitHub Bot
Jan 14, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Restored change (#48529)
parent
68d0c89f
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
315 additions
and
28 deletions
+315
-28
implicit_animations.dart
packages/flutter/lib/src/widgets/implicit_animations.dart
+137
-0
implicit_animations_test.dart
packages/flutter/test/widgets/implicit_animations_test.dart
+178
-28
No files found.
packages/flutter/lib/src/widgets/implicit_animations.dart
View file @
5ca4cc88
...
@@ -1293,6 +1293,8 @@ class _AnimatedPositionedDirectionalState extends AnimatedWidgetBaseState<Animat
...
@@ -1293,6 +1293,8 @@ class _AnimatedPositionedDirectionalState extends AnimatedWidgetBaseState<Animat
/// * [AnimatedSwitcher], for fading between many children in sequence.
/// * [AnimatedSwitcher], for fading between many children in sequence.
/// * [FadeTransition], an explicitly animated version of this widget, where
/// * [FadeTransition], an explicitly animated version of this widget, where
/// an [Animation] is provided by the caller instead of being built in.
/// an [Animation] is provided by the caller instead of being built in.
/// * [SliverAnimatedOpacity], for automatically transitioning a sliver's
/// opacity over a given duration whenever the given opacity changes.
class
AnimatedOpacity
extends
ImplicitlyAnimatedWidget
{
class
AnimatedOpacity
extends
ImplicitlyAnimatedWidget
{
/// Creates a widget that animates its opacity implicitly.
/// Creates a widget that animates its opacity implicitly.
///
///
...
@@ -1366,6 +1368,141 @@ class _AnimatedOpacityState extends ImplicitlyAnimatedWidgetState<AnimatedOpacit
...
@@ -1366,6 +1368,141 @@ class _AnimatedOpacityState extends ImplicitlyAnimatedWidgetState<AnimatedOpacit
}
}
}
}
/// Animated version of [SliverOpacity] which automatically transitions the
/// sliver child's opacity over a given duration whenever the given opacity
/// changes.
///
/// Animating an opacity is relatively expensive because it requires painting
/// the sliver child into an intermediate buffer.
///
/// Here's an illustration of what using this widget looks like, using a [curve]
/// of [Curves.fastOutSlowIn].
///
/// {@animation 250 266 https://flutter.github.io/assets-for-api-docs/assets/widgets/animated_opacity.mp4}
///
/// {@tool sample --template=stateful_widget_scaffold_center_freeform_state}
/// Creates a [CustomScrollView] with a [SliverFixedExtentList] and a
/// [FloatingActionButton]. Pressing the button animates the lists' opacity.
///
/// ```dart
/// class _MyStatefulWidgetState extends State<MyStatefulWidget> with SingleTickerProviderStateMixin {
/// bool _visible = true;
///
/// Widget build(BuildContext context) {
/// return CustomScrollView(
/// slivers: <Widget>[
/// SliverAnimatedOpacity(
/// opacity: _visible ? 1.0 : 0.0,
/// duration: Duration(milliseconds: 500),
/// sliver: SliverFixedExtentList(
/// itemExtent: 100.0,
/// delegate: SliverChildBuilderDelegate(
/// (BuildContext context, int index) {
/// return Container(
/// color: index % 2 == 0
/// ? Colors.indigo[200]
/// : Colors.orange[200],
/// );
/// },
/// childCount: 5,
/// ),
/// ),
/// ),
/// SliverToBoxAdapter(
/// child: FloatingActionButton(
/// onPressed: () {
/// setState(() {
/// _visible = !_visible;
/// });
/// },
/// tooltip: 'Toggle opacity',
/// child: Icon(Icons.flip),
/// )
/// ),
/// ]
/// );
/// }
/// }
/// ```
/// {@end-tool}
///
/// See also:
///
/// * [SliverFadeTransition], an explicitly animated version of this widget, where
/// an [Animation] is provided by the caller instead of being built in.
/// * [AnimatedOpacity], for automatically transitioning a box child's
/// opacity over a given duration whenever the given opacity changes.
class
SliverAnimatedOpacity
extends
ImplicitlyAnimatedWidget
{
/// Creates a widget that animates its opacity implicitly.
///
/// The [opacity] argument must not be null and must be between 0.0 and 1.0,
/// inclusive. The [curve] and [duration] arguments must not be null.
const
SliverAnimatedOpacity
({
Key
key
,
this
.
sliver
,
@required
this
.
opacity
,
Curve
curve
=
Curves
.
linear
,
@required
Duration
duration
,
VoidCallback
onEnd
,
this
.
alwaysIncludeSemantics
=
false
,
})
:
assert
(
opacity
!=
null
&&
opacity
>=
0.0
&&
opacity
<=
1.0
),
super
(
key:
key
,
curve:
curve
,
duration:
duration
,
onEnd:
onEnd
);
/// The sliver below this widget in the tree.
final
Widget
sliver
;
/// The target opacity.
///
/// An opacity of 1.0 is fully opaque. An opacity of 0.0 is fully transparent
/// (i.e., invisible).
///
/// The opacity must not be null.
final
double
opacity
;
/// Whether the semantic information of the children is always included.
///
/// Defaults to false.
///
/// When true, regardless of the opacity settings the sliver child's semantic
/// information is exposed as if the widget were fully visible. This is
/// useful in cases where labels may be hidden during animations that
/// would otherwise contribute relevant semantics.
final
bool
alwaysIncludeSemantics
;
@override
_SliverAnimatedOpacityState
createState
()
=>
_SliverAnimatedOpacityState
();
@override
void
debugFillProperties
(
DiagnosticPropertiesBuilder
properties
)
{
super
.
debugFillProperties
(
properties
);
properties
.
add
(
DoubleProperty
(
'opacity'
,
opacity
));
}
}
class
_SliverAnimatedOpacityState
extends
ImplicitlyAnimatedWidgetState
<
SliverAnimatedOpacity
>
{
Tween
<
double
>
_opacity
;
Animation
<
double
>
_opacityAnimation
;
@override
void
forEachTween
(
TweenVisitor
<
dynamic
>
visitor
)
{
_opacity
=
visitor
(
_opacity
,
widget
.
opacity
,
(
dynamic
value
)
=>
Tween
<
double
>(
begin:
value
as
double
))
as
Tween
<
double
>;
}
@override
void
didUpdateTweens
()
{
_opacityAnimation
=
animation
.
drive
(
_opacity
);
}
@override
Widget
build
(
BuildContext
context
)
{
return
SliverFadeTransition
(
opacity:
_opacityAnimation
,
sliver:
widget
.
sliver
,
alwaysIncludeSemantics:
widget
.
alwaysIncludeSemantics
,
);
}
}
/// Animated version of [DefaultTextStyle] which automatically transitions the
/// Animated version of [DefaultTextStyle] which automatically transitions the
/// default text style (the text style to apply to descendant [Text] widgets
/// default text style (the text style to apply to descendant [Text] widgets
/// without explicit style) over a given duration whenever the given style
/// without explicit style) over a given duration whenever the given style
...
...
packages/flutter/test/widgets/implicit_animations_test.dart
View file @
5ca4cc88
...
@@ -69,7 +69,11 @@ void main() {
...
@@ -69,7 +69,11 @@ void main() {
testWidgets
(
'AnimatedContainer onEnd callback test'
,
(
WidgetTester
tester
)
async
{
testWidgets
(
'AnimatedContainer onEnd callback test'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
wrap
(
await
tester
.
pumpWidget
(
wrap
(
child:
TestAnimatedWidget
(
callback:
mockOnEndFunction
,
switchKey:
switchKey
,
state:
_TestAnimatedContainerWidgetState
(),)
child:
TestAnimatedWidget
(
callback:
mockOnEndFunction
,
switchKey:
switchKey
,
state:
_TestAnimatedContainerWidgetState
(),
)
));
));
final
Finder
widgetFinder
=
find
.
byKey
(
switchKey
);
final
Finder
widgetFinder
=
find
.
byKey
(
switchKey
);
...
@@ -86,7 +90,11 @@ void main() {
...
@@ -86,7 +90,11 @@ void main() {
testWidgets
(
'AnimatedPadding onEnd callback test'
,
(
WidgetTester
tester
)
async
{
testWidgets
(
'AnimatedPadding onEnd callback test'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
wrap
(
await
tester
.
pumpWidget
(
wrap
(
child:
TestAnimatedWidget
(
callback:
mockOnEndFunction
,
switchKey:
switchKey
,
state:
_TestAnimatedPaddingWidgetState
(),)
child:
TestAnimatedWidget
(
callback:
mockOnEndFunction
,
switchKey:
switchKey
,
state:
_TestAnimatedPaddingWidgetState
(),
)
));
));
final
Finder
widgetFinder
=
find
.
byKey
(
switchKey
);
final
Finder
widgetFinder
=
find
.
byKey
(
switchKey
);
...
@@ -103,7 +111,11 @@ void main() {
...
@@ -103,7 +111,11 @@ void main() {
testWidgets
(
'AnimatedAlign onEnd callback test'
,
(
WidgetTester
tester
)
async
{
testWidgets
(
'AnimatedAlign onEnd callback test'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
wrap
(
await
tester
.
pumpWidget
(
wrap
(
child:
TestAnimatedWidget
(
callback:
mockOnEndFunction
,
switchKey:
switchKey
,
state:
_TestAnimatedAlignWidgetState
(),)
child:
TestAnimatedWidget
(
callback:
mockOnEndFunction
,
switchKey:
switchKey
,
state:
_TestAnimatedAlignWidgetState
(),
)
));
));
final
Finder
widgetFinder
=
find
.
byKey
(
switchKey
);
final
Finder
widgetFinder
=
find
.
byKey
(
switchKey
);
...
@@ -120,7 +132,11 @@ void main() {
...
@@ -120,7 +132,11 @@ void main() {
testWidgets
(
'AnimatedPositioned onEnd callback test'
,
(
WidgetTester
tester
)
async
{
testWidgets
(
'AnimatedPositioned onEnd callback test'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
wrap
(
await
tester
.
pumpWidget
(
wrap
(
child:
TestAnimatedWidget
(
callback:
mockOnEndFunction
,
switchKey:
switchKey
,
state:
_TestAnimatedPositionedWidgetState
(),)
child:
TestAnimatedWidget
(
callback:
mockOnEndFunction
,
switchKey:
switchKey
,
state:
_TestAnimatedPositionedWidgetState
(),
)
));
));
final
Finder
widgetFinder
=
find
.
byKey
(
switchKey
);
final
Finder
widgetFinder
=
find
.
byKey
(
switchKey
);
...
@@ -137,7 +153,11 @@ void main() {
...
@@ -137,7 +153,11 @@ void main() {
testWidgets
(
'AnimatedPositionedDirectional onEnd callback test'
,
(
WidgetTester
tester
)
async
{
testWidgets
(
'AnimatedPositionedDirectional onEnd callback test'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
wrap
(
await
tester
.
pumpWidget
(
wrap
(
child:
TestAnimatedWidget
(
callback:
mockOnEndFunction
,
switchKey:
switchKey
,
state:
_TestAnimatedPositionedDirectionalWidgetState
(),)
child:
TestAnimatedWidget
(
callback:
mockOnEndFunction
,
switchKey:
switchKey
,
state:
_TestAnimatedPositionedDirectionalWidgetState
(),
)
));
));
final
Finder
widgetFinder
=
find
.
byKey
(
switchKey
);
final
Finder
widgetFinder
=
find
.
byKey
(
switchKey
);
...
@@ -154,7 +174,58 @@ void main() {
...
@@ -154,7 +174,58 @@ void main() {
testWidgets
(
'AnimatedOpacity onEnd callback test'
,
(
WidgetTester
tester
)
async
{
testWidgets
(
'AnimatedOpacity onEnd callback test'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
wrap
(
await
tester
.
pumpWidget
(
wrap
(
child:
TestAnimatedWidget
(
callback:
mockOnEndFunction
,
switchKey:
switchKey
,
state:
_TestAnimatedOpacityWidgetState
(),)
child:
TestAnimatedWidget
(
callback:
mockOnEndFunction
,
switchKey:
switchKey
,
state:
_TestAnimatedOpacityWidgetState
(),
)
));
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
(
'AnimatedOpacity transition test'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
wrap
(
child:
TestAnimatedWidget
(
switchKey:
switchKey
,
state:
_TestAnimatedOpacityWidgetState
(),
)
));
final
Finder
switchFinder
=
find
.
byKey
(
switchKey
);
final
FadeTransition
opacityWidget
=
tester
.
widget
<
FadeTransition
>(
find
.
ancestor
(
of:
find
.
byType
(
Placeholder
),
matching:
find
.
byType
(
FadeTransition
),
).
first
,
);
await
tester
.
tap
(
switchFinder
);
await
tester
.
pump
();
expect
(
opacityWidget
.
opacity
.
value
,
equals
(
0.0
));
await
tester
.
pump
(
const
Duration
(
milliseconds:
500
));
expect
(
opacityWidget
.
opacity
.
value
,
equals
(
0.5
));
await
tester
.
pump
(
const
Duration
(
milliseconds:
250
));
expect
(
opacityWidget
.
opacity
.
value
,
equals
(
0.75
));
await
tester
.
pump
(
const
Duration
(
milliseconds:
250
));
expect
(
opacityWidget
.
opacity
.
value
,
equals
(
1.0
));
});
testWidgets
(
'SliverAnimatedOpacity onEnd callback test'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
TestAnimatedWidget
(
callback:
mockOnEndFunction
,
switchKey:
switchKey
,
state:
_TestSliverAnimatedOpacityWidgetState
(),
));
));
final
Finder
widgetFinder
=
find
.
byKey
(
switchKey
);
final
Finder
widgetFinder
=
find
.
byKey
(
switchKey
);
...
@@ -169,9 +240,41 @@ void main() {
...
@@ -169,9 +240,41 @@ void main() {
expect
(
mockOnEndFunction
.
called
,
1
);
expect
(
mockOnEndFunction
.
called
,
1
);
});
});
testWidgets
(
'SliverAnimatedOpacity transition test'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
wrap
(
child:
TestAnimatedWidget
(
switchKey:
switchKey
,
state:
_TestSliverAnimatedOpacityWidgetState
(),
)
));
final
Finder
switchFinder
=
find
.
byKey
(
switchKey
);
final
SliverFadeTransition
opacityWidget
=
tester
.
widget
<
SliverFadeTransition
>(
find
.
ancestor
(
of:
find
.
byType
(
Placeholder
),
matching:
find
.
byType
(
SliverFadeTransition
),
).
first
,
);
await
tester
.
tap
(
switchFinder
);
await
tester
.
pump
();
expect
(
opacityWidget
.
opacity
.
value
,
equals
(
0.0
));
await
tester
.
pump
(
const
Duration
(
milliseconds:
500
));
expect
(
opacityWidget
.
opacity
.
value
,
equals
(
0.5
));
await
tester
.
pump
(
const
Duration
(
milliseconds:
250
));
expect
(
opacityWidget
.
opacity
.
value
,
equals
(
0.75
));
await
tester
.
pump
(
const
Duration
(
milliseconds:
250
));
expect
(
opacityWidget
.
opacity
.
value
,
equals
(
1.0
));
});
testWidgets
(
'AnimatedDefaultTextStyle onEnd callback test'
,
(
WidgetTester
tester
)
async
{
testWidgets
(
'AnimatedDefaultTextStyle onEnd callback test'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
wrap
(
await
tester
.
pumpWidget
(
wrap
(
child:
TestAnimatedWidget
(
callback:
mockOnEndFunction
,
switchKey:
switchKey
,
state:
_TestAnimatedDefaultTextStyleWidgetState
(),)
child:
TestAnimatedWidget
(
callback:
mockOnEndFunction
,
switchKey:
switchKey
,
state:
_TestAnimatedDefaultTextStyleWidgetState
(),
)
));
));
final
Finder
widgetFinder
=
find
.
byKey
(
switchKey
);
final
Finder
widgetFinder
=
find
.
byKey
(
switchKey
);
...
@@ -188,7 +291,11 @@ void main() {
...
@@ -188,7 +291,11 @@ void main() {
testWidgets
(
'AnimatedPhysicalModel onEnd callback test'
,
(
WidgetTester
tester
)
async
{
testWidgets
(
'AnimatedPhysicalModel onEnd callback test'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
wrap
(
await
tester
.
pumpWidget
(
wrap
(
child:
TestAnimatedWidget
(
callback:
mockOnEndFunction
,
switchKey:
switchKey
,
state:
_TestAnimatedPhysicalModelWidgetState
(),)
child:
TestAnimatedWidget
(
callback:
mockOnEndFunction
,
switchKey:
switchKey
,
state:
_TestAnimatedPhysicalModelWidgetState
(),
)
));
));
final
Finder
widgetFinder
=
find
.
byKey
(
switchKey
);
final
Finder
widgetFinder
=
find
.
byKey
(
switchKey
);
...
@@ -205,7 +312,11 @@ void main() {
...
@@ -205,7 +312,11 @@ void main() {
testWidgets
(
'TweenAnimationBuilder onEnd callback test'
,
(
WidgetTester
tester
)
async
{
testWidgets
(
'TweenAnimationBuilder onEnd callback test'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
wrap
(
await
tester
.
pumpWidget
(
wrap
(
child:
TestAnimatedWidget
(
callback:
mockOnEndFunction
,
switchKey:
switchKey
,
state:
_TestTweenAnimationBuilderWidgetState
(),)
child:
TestAnimatedWidget
(
callback:
mockOnEndFunction
,
switchKey:
switchKey
,
state:
_TestTweenAnimationBuilderWidgetState
(),
)
));
));
final
Finder
widgetFinder
=
find
.
byKey
(
switchKey
);
final
Finder
widgetFinder
=
find
.
byKey
(
switchKey
);
...
@@ -222,7 +333,11 @@ void main() {
...
@@ -222,7 +333,11 @@ void main() {
testWidgets
(
'AnimatedTheme onEnd callback test'
,
(
WidgetTester
tester
)
async
{
testWidgets
(
'AnimatedTheme onEnd callback test'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
wrap
(
await
tester
.
pumpWidget
(
wrap
(
child:
TestAnimatedWidget
(
callback:
mockOnEndFunction
,
switchKey:
switchKey
,
state:
_TestAnimatedThemeWidgetState
(),)
child:
TestAnimatedWidget
(
callback:
mockOnEndFunction
,
switchKey:
switchKey
,
state:
_TestAnimatedThemeWidgetState
(),
)
));
));
final
Finder
widgetFinder
=
find
.
byKey
(
switchKey
);
final
Finder
widgetFinder
=
find
.
byKey
(
switchKey
);
...
@@ -360,7 +475,42 @@ class _TestAnimatedOpacityWidgetState extends _TestAnimatedWidgetState {
...
@@ -360,7 +475,42 @@ class _TestAnimatedOpacityWidgetState extends _TestAnimatedWidgetState {
child:
child
,
child:
child
,
duration:
duration
,
duration:
duration
,
onEnd:
widget
.
callback
,
onEnd:
widget
.
callback
,
opacity:
toggle
?
0.1
:
0.9
,
opacity:
toggle
?
1.0
:
0.0
,
);
}
}
class
_TestSliverAnimatedOpacityWidgetState
extends
_TestAnimatedWidgetState
{
@override
Widget
getAnimatedWidget
()
{
return
SliverAnimatedOpacity
(
sliver:
SliverToBoxAdapter
(
child:
child
),
duration:
duration
,
onEnd:
widget
.
callback
,
opacity:
toggle
?
1.0
:
0.0
,
);
}
@override
Widget
build
(
BuildContext
context
)
{
final
Widget
animatedWidget
=
getAnimatedWidget
();
return
Material
(
child:
Directionality
(
textDirection:
TextDirection
.
ltr
,
child:
CustomScrollView
(
slivers:
<
Widget
>[
animatedWidget
,
SliverToBoxAdapter
(
child:
Switch
(
key:
widget
.
switchKey
,
value:
toggle
,
onChanged:
onChanged
,
),
),
],
),
),
);
);
}
}
}
}
...
...
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