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
345d939e
Unverified
Commit
345d939e
authored
Aug 08, 2018
by
Natalie Sampsell
Committed by
GitHub
Aug 08, 2018
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add showCupertinoDialog and showGeneralDialog (#20152)
parent
e770685a
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
427 additions
and
78 deletions
+427
-78
route.dart
packages/flutter/lib/src/cupertino/route.dart
+79
-0
dialog.dart
packages/flutter/lib/src/material/dialog.dart
+38
-66
pages.dart
packages/flutter/lib/src/widgets/pages.dart
+0
-12
routes.dart
packages/flutter/lib/src/widgets/routes.dart
+140
-0
dialog_test.dart
packages/flutter/test/cupertino/dialog_test.dart
+170
-0
No files found.
packages/flutter/lib/src/cupertino/route.dart
View file @
345d939e
...
...
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'dart:async'
;
import
'package:flutter/gestures.dart'
;
import
'package:flutter/rendering.dart'
;
import
'package:flutter/widgets.dart'
;
...
...
@@ -9,6 +11,9 @@ import 'package:flutter/widgets.dart';
const
double
_kBackGestureWidth
=
20.0
;
const
double
_kMinFlingVelocity
=
1.0
;
// Screen widths per second.
// Barrier color for a Cupertino modal barrier.
const
Color
_kModalBarrierColor
=
Color
(
0x6604040F
);
// Offset from offscreen to the right to fully on screen.
final
Tween
<
Offset
>
_kRightMiddleTween
=
new
Tween
<
Offset
>(
begin:
const
Offset
(
1.0
,
0.0
),
...
...
@@ -709,3 +714,77 @@ class _CupertinoEdgeShadowPainter extends BoxPainter {
canvas
.
drawRect
(
rect
,
paint
);
}
}
Widget
_buildCupertinoDialogTransitions
(
BuildContext
context
,
Animation
<
double
>
animation
,
Animation
<
double
>
secondaryAnimation
,
Widget
child
)
{
final
CurvedAnimation
fadeAnimation
=
new
CurvedAnimation
(
parent:
animation
,
curve:
Curves
.
easeInOut
,
);
if
(
animation
.
status
==
AnimationStatus
.
reverse
)
{
return
new
FadeTransition
(
opacity:
fadeAnimation
,
child:
child
,
);
}
return
new
FadeTransition
(
opacity:
fadeAnimation
,
child:
ScaleTransition
(
child:
child
,
scale:
new
Tween
<
double
>(
begin:
1.2
,
end:
1.0
,
).
animate
(
new
CurvedAnimation
(
parent:
animation
,
curve:
Curves
.
fastOutSlowIn
,
),
),
),
);
}
/// Displays an iOS-style dialog above the current contents of the app, with
/// iOS-style entrance and exit animations, modal barrier color, and modal
/// barrier behavior (the dialog is not dismissible with a tap on the barrier).
///
/// This function takes a `builder` which typically builds a [CupertinoDialog]
/// or [CupertinoAlertDialog] widget. Content below the dialog is dimmed with a
/// [ModalBarrier]. The widget returned by the `builder` does not share a
/// context with the location that `showCupertinoDialog` is originally called
/// from. Use a [StatefulBuilder] or a custom [StatefulWidget] if the dialog
/// needs to update dynamically.
///
/// The `context` argument is used to look up the [Navigator] for the dialog.
/// It is only used when the method is called. Its corresponding widget can
/// be safely removed from the tree before the dialog is closed.
///
/// Returns a [Future] that resolves to the value (if any) that was passed to
/// [Navigator.pop] when the dialog was closed.
///
/// The dialog route created by this method is pushed to the root navigator.
/// If the application has multiple [Navigator] objects, it may be necessary to
/// call `Navigator.of(context, rootNavigator: true).pop(result)` to close the
/// dialog rather than just `Navigator.pop(context, result)`.
///
/// See also:
/// * [CupertinoDialog], an iOS-style dialog.
/// * [CupertinoAlertDialog], an iOS-style alert dialog.
/// * [showDialog], which displays a Material-style dialog.
/// * [showGeneralDialog], which allows for customization of the dialog popup.
/// * <https://developer.apple.com/ios/human-interface-guidelines/views/alerts/>
Future
<
T
>
showCupertinoDialog
<
T
>({
@required
BuildContext
context
,
@required
WidgetBuilder
builder
,
})
{
assert
(
builder
!=
null
);
return
showGeneralDialog
(
context:
context
,
barrierDismissible:
false
,
barrierColor:
_kModalBarrierColor
,
transitionDuration:
const
Duration
(
milliseconds:
300
),
pageBuilder:
(
BuildContext
context
,
Animation
<
double
>
animation
,
Animation
<
double
>
secondaryAnimation
)
{
return
builder
(
context
);
},
transitionBuilder:
_buildCupertinoDialogTransitions
,
);
}
\ No newline at end of file
packages/flutter/lib/src/material/dialog.dart
View file @
345d939e
...
...
@@ -543,70 +543,25 @@ class SimpleDialog extends StatelessWidget {
}
}
class
_DialogRoute
<
T
>
extends
PopupRoute
<
T
>
{
_DialogRoute
({
@required
this
.
theme
,
bool
barrierDismissible
=
true
,
this
.
barrierLabel
,
@required
this
.
child
,
RouteSettings
settings
,
})
:
assert
(
barrierDismissible
!=
null
),
_barrierDismissible
=
barrierDismissible
,
super
(
settings:
settings
);
final
Widget
child
;
final
ThemeData
theme
;
@override
Duration
get
transitionDuration
=>
const
Duration
(
milliseconds:
150
);
@override
bool
get
barrierDismissible
=>
_barrierDismissible
;
final
bool
_barrierDismissible
;
@override
Color
get
barrierColor
=>
Colors
.
black54
;
@override
final
String
barrierLabel
;
@override
Widget
buildPage
(
BuildContext
context
,
Animation
<
double
>
animation
,
Animation
<
double
>
secondaryAnimation
)
{
return
new
SafeArea
(
child:
new
Builder
(
builder:
(
BuildContext
context
)
{
final
Widget
annotatedChild
=
new
Semantics
(
child:
child
,
scopesRoute:
true
,
explicitChildNodes:
true
,
);
return
theme
!=
null
?
new
Theme
(
data:
theme
,
child:
annotatedChild
)
:
annotatedChild
;
}
),
);
}
@override
Widget
buildTransitions
(
BuildContext
context
,
Animation
<
double
>
animation
,
Animation
<
double
>
secondaryAnimation
,
Widget
child
)
{
return
new
FadeTransition
(
opacity:
new
CurvedAnimation
(
parent:
animation
,
curve:
Curves
.
easeOut
),
child:
child
);
}
Widget
_buildMaterialDialogTransitions
(
BuildContext
context
,
Animation
<
double
>
animation
,
Animation
<
double
>
secondaryAnimation
,
Widget
child
)
{
return
new
FadeTransition
(
opacity:
new
CurvedAnimation
(
parent:
animation
,
curve:
Curves
.
easeOut
,
),
child:
child
,
);
}
/// Displays a dialog above the current contents of the app.
/// Displays a Material dialog above the current contents of the app, with
/// Material entrance and exit animations, modal barrier color, and modal
/// barrier behavior (dialog is dismissible with a tap on the barrier).
///
/// This function takes a `builder` which typically builds a [Dialog] widget.
/// Content below the dialog is dimmed with a [ModalBarrier]. Th
is widget does
///
not share a context with the location that `showDialog` is originally
///
called from. Use a [StatefulBuilder] or a custom [StatefulWidget] if the
/// dialog needs to update dynamically.
/// Content below the dialog is dimmed with a [ModalBarrier]. Th
e widget
///
returned by the `builder` does not share a context with the location that
///
`showDialog` is originally called from. Use a [StatefulBuilder] or a
///
custom [StatefulWidget] if the
dialog needs to update dynamically.
///
/// The `context` argument is used to look up the [Navigator] and [Theme] for
/// the dialog. It is only used when the method is called. Its corresponding
...
...
@@ -620,13 +575,15 @@ class _DialogRoute<T> extends PopupRoute<T> {
/// The dialog route created by this method is pushed to the root navigator.
/// If the application has multiple [Navigator] objects, it may be necessary to
/// call `Navigator.of(context, rootNavigator: true).pop(result)` to close the
/// dialog rather
just '
Navigator.pop(context, result)`.
/// dialog rather
than just `
Navigator.pop(context, result)`.
///
/// See also:
/// * [AlertDialog], for dialogs that have a row of buttons below a body.
/// * [SimpleDialog], which handles the scrolling of the contents and does
/// not show buttons below its body.
/// * [Dialog], on which [SimpleDialog] and [AlertDialog] are based.
/// * [showCupertinoDialog], which displays an iOS-style dialog.
/// * [showGeneralDialog], which allows for customization of the dialog popup.
/// * <https://material.google.com/components/dialogs.html>
Future
<
T
>
showDialog
<
T
>({
@required
BuildContext
context
,
...
...
@@ -639,10 +596,25 @@ Future<T> showDialog<T>({
WidgetBuilder
builder
,
})
{
assert
(
child
==
null
||
builder
==
null
);
return
Navigator
.
of
(
context
,
rootNavigator:
true
).
push
(
new
_DialogRoute
<
T
>(
child:
child
??
new
Builder
(
builder:
builder
),
theme:
Theme
.
of
(
context
,
shadowThemeOnly:
true
),
return
showGeneralDialog
(
context:
context
,
pageBuilder:
(
BuildContext
buildContext
,
Animation
<
double
>
animation
,
Animation
<
double
>
secondaryAnimation
)
{
final
ThemeData
theme
=
Theme
.
of
(
context
,
shadowThemeOnly:
true
);
final
Widget
pageChild
=
child
??
new
Builder
(
builder:
builder
);
return
new
SafeArea
(
child:
new
Builder
(
builder:
(
BuildContext
context
)
{
return
theme
!=
null
?
new
Theme
(
data:
theme
,
child:
pageChild
)
:
pageChild
;
}
),
);
},
barrierDismissible:
barrierDismissible
,
barrierLabel:
MaterialLocalizations
.
of
(
context
).
modalBarrierDismissLabel
,
));
}
barrierColor:
Colors
.
black54
,
transitionDuration:
const
Duration
(
milliseconds:
150
),
transitionBuilder:
_buildMaterialDialogTransitions
,
);
}
\ No newline at end of file
packages/flutter/lib/src/widgets/pages.dart
View file @
345d939e
...
...
@@ -44,18 +44,6 @@ abstract class PageRoute<T> extends ModalRoute<T> {
}
}
/// Signature for the [PageRouteBuilder] function that builds the route's
/// primary contents.
///
/// See [ModalRoute.buildPage] for complete definition of the parameters.
typedef
Widget
RoutePageBuilder
(
BuildContext
context
,
Animation
<
double
>
animation
,
Animation
<
double
>
secondaryAnimation
);
/// Signature for the [PageRouteBuilder] function that builds the route's
/// transitions.
///
/// See [ModalRoute.buildTransitions] for complete definition of the parameters.
typedef
Widget
RouteTransitionsBuilder
(
BuildContext
context
,
Animation
<
double
>
animation
,
Animation
<
double
>
secondaryAnimation
,
Widget
child
);
Widget
_defaultTransitionsBuilder
(
BuildContext
context
,
Animation
<
double
>
animation
,
Animation
<
double
>
secondaryAnimation
,
Widget
child
)
{
return
child
;
}
...
...
packages/flutter/lib/src/widgets/routes.dart
View file @
345d939e
...
...
@@ -1379,3 +1379,143 @@ abstract class RouteAware {
/// longer visible.
void
didPushNext
()
{
}
}
class
_DialogRoute
<
T
>
extends
PopupRoute
<
T
>
{
_DialogRoute
({
@required
RoutePageBuilder
pageBuilder
,
bool
barrierDismissible
=
true
,
String
barrierLabel
,
Color
barrierColor
=
const
Color
(
0x80000000
),
Duration
transitionDuration
=
const
Duration
(
milliseconds:
200
),
RouteTransitionsBuilder
transitionBuilder
,
RouteSettings
settings
,
})
:
assert
(
barrierDismissible
!=
null
),
_pageBuilder
=
pageBuilder
,
_barrierDismissible
=
barrierDismissible
,
_barrierLabel
=
barrierLabel
,
_barrierColor
=
barrierColor
,
_transitionDuration
=
transitionDuration
,
_transitionBuilder
=
transitionBuilder
,
super
(
settings:
settings
);
final
RoutePageBuilder
_pageBuilder
;
@override
bool
get
barrierDismissible
=>
_barrierDismissible
;
final
bool
_barrierDismissible
;
@override
String
get
barrierLabel
=>
_barrierLabel
;
final
String
_barrierLabel
;
@override
Color
get
barrierColor
=>
_barrierColor
;
final
Color
_barrierColor
;
@override
Duration
get
transitionDuration
=>
_transitionDuration
;
final
Duration
_transitionDuration
;
final
RouteTransitionsBuilder
_transitionBuilder
;
@override
Widget
buildPage
(
BuildContext
context
,
Animation
<
double
>
animation
,
Animation
<
double
>
secondaryAnimation
)
{
return
new
Semantics
(
child:
_pageBuilder
(
context
,
animation
,
secondaryAnimation
),
scopesRoute:
true
,
explicitChildNodes:
true
,
);
}
@override
Widget
buildTransitions
(
BuildContext
context
,
Animation
<
double
>
animation
,
Animation
<
double
>
secondaryAnimation
,
Widget
child
)
{
if
(
_transitionBuilder
==
null
)
{
return
new
FadeTransition
(
opacity:
new
CurvedAnimation
(
parent:
animation
,
curve:
Curves
.
linear
,
),
child:
child
);
}
// Some default transition
return
_transitionBuilder
(
context
,
animation
,
secondaryAnimation
,
child
);
}
}
/// Displays a dialog above the current contents of the app.
///
/// This function allows for customization of aspects of the dialog popup.
///
/// This function takes a `pageBuilder` which is used to build the primary
/// content of the route (typically a dialog widget). Content below the dialog
/// is dimmed with a [ModalBarrier]. The widget returned by the `pageBuilder`
/// does not share a context with the location that `showGeneralDialog` is
/// originally called from. Use a [StatefulBuilder] or a custom
/// [StatefulWidget] if the dialog needs to update dynamically. The
/// `pageBuilder` argument can not be null.
///
/// The `context` argument is used to look up the [Navigator] for the dialog.
/// It is only used when the method is called. Its corresponding widget can
/// be safely removed from the tree before the dialog is closed.
///
/// The `barrierDismissible` argument is used to determine whether this route
/// can be dismissed by tapping the modal barrier. This argument defaults
/// to true. If `barrierDismissible` is true, a non-null `barrierLabel` must be
/// provided.
///
/// The `barrierLabel` argument is the semantic label used for a dismissible
/// barrier. This argument defaults to "Dismiss".
///
/// The `barrierColor` argument is the color used for the modal barrier. This
/// argument defaults to `Color(0x80000000)`.
///
/// The `transitionDuration` argument is used to determine how long it takes
/// for the route to arrive on or leave off the screen. This argument defaults
/// to 200 milliseconds.
///
/// The `transitionBuilder` argument is used to define how the route arrives on
/// and leaves off the screen. By default, the transition is a linear fade of
/// the page's contents.
///
/// Returns a [Future] that resolves to the value (if any) that was passed to
/// [Navigator.pop] when the dialog was closed.
///
/// The dialog route created by this method is pushed to the root navigator.
/// If the application has multiple [Navigator] objects, it may be necessary to
/// call `Navigator.of(context, rootNavigator: true).pop(result)` to close the
/// dialog rather than just `Navigator.pop(context, result)`.
///
/// See also:
/// * [showDialog], which displays a Material-style dialog.
/// * [showCupertinoDialog], which displays an iOS-style dialog.
Future
<
T
>
showGeneralDialog
<
T
>({
@required
BuildContext
context
,
@required
RoutePageBuilder
pageBuilder
,
bool
barrierDismissible
,
String
barrierLabel
,
Color
barrierColor
,
Duration
transitionDuration
,
RouteTransitionsBuilder
transitionBuilder
,
})
{
assert
(
pageBuilder
!=
null
);
assert
(!
barrierDismissible
||
barrierLabel
!=
null
);
return
Navigator
.
of
(
context
,
rootNavigator:
true
).
push
(
new
_DialogRoute
<
T
>(
pageBuilder:
pageBuilder
,
barrierDismissible:
barrierDismissible
,
barrierLabel:
barrierLabel
,
barrierColor:
barrierColor
,
transitionDuration:
transitionDuration
,
transitionBuilder:
transitionBuilder
,
));
}
/// Signature for the function that builds a route's primary contents.
/// Used in [PageRouteBuilder] and [showGeneralDialog].
///
/// See [ModalRoute.buildPage] for complete definition of the parameters.
typedef
Widget
RoutePageBuilder
(
BuildContext
context
,
Animation
<
double
>
animation
,
Animation
<
double
>
secondaryAnimation
);
/// Signature for the function that builds a route's transitions.
/// Used in [PageRouteBuilder] and [showGeneralDialog].
///
/// See [ModalRoute.buildTransitions] for complete definition of the parameters.
typedef
Widget
RouteTransitionsBuilder
(
BuildContext
context
,
Animation
<
double
>
animation
,
Animation
<
double
>
secondaryAnimation
,
Widget
child
);
packages/flutter/test/cupertino/dialog_test.dart
View file @
345d939e
...
...
@@ -332,6 +332,176 @@ void main() {
expect
(
scrollController
.
offset
,
0.0
);
expect
(
find
.
widgetWithText
(
CupertinoDialogAction
,
'One'
),
findsNothing
);
});
testWidgets
(
'ScaleTransition animation for showCupertinoDialog()'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
new
CupertinoApp
(
home:
new
Center
(
child:
new
Builder
(
builder:
(
BuildContext
context
)
{
return
new
CupertinoButton
(
onPressed:
()
{
showCupertinoDialog
<
void
>(
context:
context
,
builder:
(
BuildContext
context
)
{
return
new
CupertinoAlertDialog
(
title:
const
Text
(
'The title'
),
content:
const
Text
(
'The content'
),
actions:
<
Widget
>[
const
CupertinoDialogAction
(
child:
Text
(
'Cancel'
),
),
new
CupertinoDialogAction
(
isDestructiveAction:
true
,
onPressed:
()
{
Navigator
.
pop
(
context
);
},
child:
const
Text
(
'Delete'
),
),
],
);
},
);
},
child:
const
Text
(
'Go'
),
);
},
),
),
),
);
await
tester
.
tap
(
find
.
text
(
'Go'
));
// Enter animation.
await
tester
.
pump
();
Transform
transform
=
tester
.
widget
(
find
.
byType
(
Transform
));
expect
(
transform
.
transform
[
0
],
closeTo
(
1.2
,
0.01
));
await
tester
.
pump
(
const
Duration
(
milliseconds:
50
));
transform
=
tester
.
widget
(
find
.
byType
(
Transform
));
expect
(
transform
.
transform
[
0
],
closeTo
(
1.182
,
0.001
));
await
tester
.
pump
(
const
Duration
(
milliseconds:
50
));
transform
=
tester
.
widget
(
find
.
byType
(
Transform
));
expect
(
transform
.
transform
[
0
],
closeTo
(
1.108
,
0.001
));
await
tester
.
pump
(
const
Duration
(
milliseconds:
50
));
transform
=
tester
.
widget
(
find
.
byType
(
Transform
));
expect
(
transform
.
transform
[
0
],
closeTo
(
1.044
,
0.001
));
await
tester
.
pump
(
const
Duration
(
milliseconds:
50
));
transform
=
tester
.
widget
(
find
.
byType
(
Transform
));
expect
(
transform
.
transform
[
0
],
closeTo
(
1.015
,
0.001
));
await
tester
.
pump
(
const
Duration
(
milliseconds:
50
));
transform
=
tester
.
widget
(
find
.
byType
(
Transform
));
expect
(
transform
.
transform
[
0
],
closeTo
(
1.003
,
0.001
));
await
tester
.
pump
(
const
Duration
(
milliseconds:
50
));
transform
=
tester
.
widget
(
find
.
byType
(
Transform
));
expect
(
transform
.
transform
[
0
],
closeTo
(
1.000
,
0.001
));
await
tester
.
tap
(
find
.
text
(
'Delete'
));
await
tester
.
pump
();
await
tester
.
pump
(
const
Duration
(
milliseconds:
50
));
// No scaling on exit animation.
expect
(
find
.
byType
(
Transform
),
findsNothing
);
});
testWidgets
(
'FadeTransition animation for showCupertinoDialog()'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
new
CupertinoApp
(
home:
new
Center
(
child:
new
Builder
(
builder:
(
BuildContext
context
)
{
return
new
CupertinoButton
(
onPressed:
()
{
showCupertinoDialog
<
void
>(
context:
context
,
builder:
(
BuildContext
context
)
{
return
new
CupertinoAlertDialog
(
title:
const
Text
(
'The title'
),
content:
const
Text
(
'The content'
),
actions:
<
Widget
>[
const
CupertinoDialogAction
(
child:
Text
(
'Cancel'
),
),
new
CupertinoDialogAction
(
isDestructiveAction:
true
,
onPressed:
()
{
Navigator
.
pop
(
context
);
},
child:
const
Text
(
'Delete'
),
),
],
);
},
);
},
child:
const
Text
(
'Go'
),
);
},
),
),
),
);
await
tester
.
tap
(
find
.
text
(
'Go'
));
// Enter animation.
await
tester
.
pump
();
FadeTransition
transition
=
tester
.
firstWidget
(
find
.
byType
(
FadeTransition
));
await
tester
.
pump
(
const
Duration
(
milliseconds:
25
));
transition
=
tester
.
firstWidget
(
find
.
byType
(
FadeTransition
));
expect
(
transition
.
opacity
.
value
,
closeTo
(
0.10
,
0.001
));
await
tester
.
pump
(
const
Duration
(
milliseconds:
25
));
transition
=
tester
.
firstWidget
(
find
.
byType
(
FadeTransition
));
expect
(
transition
.
opacity
.
value
,
closeTo
(
0.156
,
0.001
));
await
tester
.
pump
(
const
Duration
(
milliseconds:
25
));
transition
=
tester
.
firstWidget
(
find
.
byType
(
FadeTransition
));
expect
(
transition
.
opacity
.
value
,
closeTo
(
0.324
,
0.001
));
await
tester
.
pump
(
const
Duration
(
milliseconds:
25
));
transition
=
tester
.
firstWidget
(
find
.
byType
(
FadeTransition
));
expect
(
transition
.
opacity
.
value
,
closeTo
(
0.606
,
0.001
));
await
tester
.
pump
(
const
Duration
(
milliseconds:
25
));
transition
=
tester
.
firstWidget
(
find
.
byType
(
FadeTransition
));
expect
(
transition
.
opacity
.
value
,
closeTo
(
1.0
,
0.001
));
await
tester
.
tap
(
find
.
text
(
'Delete'
));
// Exit animation, look at reverse FadeTransition.
await
tester
.
pump
(
const
Duration
(
milliseconds:
25
));
transition
=
tester
.
widgetList
(
find
.
byType
(
FadeTransition
)).
elementAt
(
1
);
expect
(
transition
.
opacity
.
value
,
closeTo
(
0.358
,
0.001
));
await
tester
.
pump
(
const
Duration
(
milliseconds:
25
));
transition
=
tester
.
widgetList
(
find
.
byType
(
FadeTransition
)).
elementAt
(
1
);
expect
(
transition
.
opacity
.
value
,
closeTo
(
0.231
,
0.001
));
await
tester
.
pump
(
const
Duration
(
milliseconds:
25
));
transition
=
tester
.
widgetList
(
find
.
byType
(
FadeTransition
)).
elementAt
(
1
);
expect
(
transition
.
opacity
.
value
,
closeTo
(
0.128
,
0.001
));
await
tester
.
pump
(
const
Duration
(
milliseconds:
25
));
transition
=
tester
.
widgetList
(
find
.
byType
(
FadeTransition
)).
elementAt
(
1
);
expect
(
transition
.
opacity
.
value
,
closeTo
(
0.056
,
0.001
));
await
tester
.
pump
(
const
Duration
(
milliseconds:
25
));
transition
=
tester
.
widgetList
(
find
.
byType
(
FadeTransition
)).
elementAt
(
1
);
expect
(
transition
.
opacity
.
value
,
closeTo
(
0.013
,
0.001
));
await
tester
.
pump
(
const
Duration
(
milliseconds:
25
));
transition
=
tester
.
widgetList
(
find
.
byType
(
FadeTransition
)).
elementAt
(
1
);
expect
(
transition
.
opacity
.
value
,
closeTo
(
0.0
,
0.001
));
});
}
Widget
boilerplate
(
Widget
child
)
{
...
...
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