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
13860a7d
Unverified
Commit
13860a7d
authored
Sep 10, 2020
by
Hans Muller
Committed by
GitHub
Sep 10, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Revert "Re-land ScaffoldMessenger (#65416)" (#65482)
This reverts commit
adc5f26b
.
parent
ee4fa1b3
Changes
11
Show whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
302 additions
and
820 deletions
+302
-820
app.dart
packages/flutter/lib/src/material/app.dart
+21
-35
app_bar.dart
packages/flutter/lib/src/material/app_bar.dart
+1
-1
debug.dart
packages/flutter/lib/src/material/debug.dart
+1
-32
scaffold.dart
packages/flutter/lib/src/material/scaffold.dart
+152
-483
snack_bar.dart
packages/flutter/lib/src/material/snack_bar.dart
+18
-20
animated_list.dart
packages/flutter/lib/src/widgets/animated_list.dart
+1
-3
framework.dart
packages/flutter/lib/src/widgets/framework.dart
+21
-40
debug_test.dart
packages/flutter/test/material/debug_test.dart
+0
-48
floating_action_button_location_test.dart
...r/test/material/floating_action_button_location_test.dart
+1
-1
snack_bar_test.dart
packages/flutter/test/material/snack_bar_test.dart
+81
-152
snack_bar_theme_test.dart
packages/flutter/test/material/snack_bar_theme_test.dart
+5
-5
No files found.
packages/flutter/lib/src/material/app.dart
View file @
13860a7d
...
...
@@ -17,7 +17,6 @@ import 'floating_action_button.dart';
import
'icons.dart'
;
import
'material_localizations.dart'
;
import
'page.dart'
;
import
'scaffold.dart'
;
import
'theme.dart'
;
/// [MaterialApp] uses this [TextStyle] as its [DefaultTextStyle] to encourage
...
...
@@ -169,7 +168,6 @@ class MaterialApp extends StatefulWidget {
const
MaterialApp
({
Key
key
,
this
.
navigatorKey
,
this
.
scaffoldMessengerKey
,
this
.
home
,
this
.
routes
=
const
<
String
,
WidgetBuilder
>{},
this
.
initialRoute
,
...
...
@@ -217,7 +215,6 @@ class MaterialApp extends StatefulWidget {
/// Creates a [MaterialApp] that uses the [Router] instead of a [Navigator].
const
MaterialApp
.
router
({
Key
key
,
this
.
scaffoldMessengerKey
,
this
.
routeInformationProvider
,
@required
this
.
routeInformationParser
,
@required
this
.
routerDelegate
,
...
...
@@ -266,14 +263,6 @@ class MaterialApp extends StatefulWidget {
/// {@macro flutter.widgets.widgetsApp.navigatorKey}
final
GlobalKey
<
NavigatorState
>
navigatorKey
;
/// A key to use when building the [ScaffoldMessenger].
///
/// If a [scaffoldMessengerKey] is specified, the [ScaffoldMessenger] can be
/// directly manipulated without first obtaining it from a [BuildContext] via
/// [ScaffoldMessenger.of]: from the [scaffoldMessengerKey], use the
/// [GlobalKey.currentState] getter.
final
GlobalKey
<
ScaffoldMessengerState
>
scaffoldMessengerKey
;
/// {@macro flutter.widgets.widgetsApp.home}
final
Widget
home
;
...
...
@@ -733,9 +722,7 @@ class _MaterialAppState extends State<MaterialApp> {
}
theme
??=
widget
.
theme
??
ThemeData
.
light
();
return
ScaffoldMessenger
(
key:
widget
.
scaffoldMessengerKey
,
child:
AnimatedTheme
(
return
AnimatedTheme
(
data:
theme
,
isMaterialAppTheme:
true
,
child:
widget
.
builder
!=
null
...
...
@@ -756,7 +743,6 @@ class _MaterialAppState extends State<MaterialApp> {
},
)
:
child
,
)
);
}
...
...
packages/flutter/lib/src/material/app_bar.dart
View file @
13860a7d
...
...
@@ -137,7 +137,7 @@ class _ToolbarContainerLayout extends SingleChildLayoutDelegate {
/// icon: const Icon(Icons.add_alert),
/// tooltip: 'Show Snackbar',
/// onPressed: () {
///
ScaffoldMessenger.of(context)
.showSnackBar(snackBar);
///
scaffoldKey.currentState
.showSnackBar(snackBar);
/// },
/// ),
/// IconButton(
...
...
packages/flutter/lib/src/material/debug.dart
View file @
13860a7d
...
...
@@ -9,7 +9,7 @@ import 'package:flutter/widgets.dart';
import
'material.dart'
;
import
'material_localizations.dart'
;
import
'scaffold.dart'
show
Scaffold
,
ScaffoldMessenger
;
import
'scaffold.dart'
show
Scaffold
;
/// Asserts that the given context has a [Material] ancestor.
///
...
...
@@ -125,34 +125,3 @@ bool debugCheckHasScaffold(BuildContext context) {
}());
return
true
;
}
/// Asserts that the given context has a [ScaffoldMessenger] ancestor.
///
/// Used by various widgets to make sure that they are only used in an
/// appropriate context.
///
/// To invoke this function, use the following pattern, typically in the
/// relevant Widget's build method:
///
/// ```dart
/// assert(debugCheckHasScaffoldMessenger(context));
/// ```
///
/// Does nothing if asserts are disabled. Always returns true.
bool
debugCheckHasScaffoldMessenger
(
BuildContext
context
)
{
assert
(()
{
if
(
context
.
widget
is
!
ScaffoldMessenger
&&
context
.
findAncestorWidgetOfExactType
<
ScaffoldMessenger
>()
==
null
)
{
throw
FlutterError
.
fromParts
(<
DiagnosticsNode
>[
ErrorSummary
(
'No ScaffoldMessenger widget found.'
),
ErrorDescription
(
'
${context.widget.runtimeType}
widgets require a ScaffoldMessenger widget ancestor.'
),
...
context
.
describeMissingAncestor
(
expectedAncestorType:
ScaffoldMessenger
),
ErrorHint
(
'Typically, the ScaffoldMessenger widget is introduced by the MaterialApp '
'at the top of your application widget tree.'
)
]);
}
return
true
;
}());
return
true
;
}
packages/flutter/lib/src/material/scaffold.dart
View file @
13860a7d
...
...
@@ -19,7 +19,6 @@ import 'bottom_sheet.dart';
import
'button_bar.dart'
;
import
'colors.dart'
;
import
'curves.dart'
;
import
'debug.dart'
;
import
'divider.dart'
;
import
'drawer.dart'
;
import
'flexible_space_bar.dart'
;
...
...
@@ -62,372 +61,6 @@ enum _ScaffoldSlot {
statusBar
,
}
/// Manages [SnackBar]s for descendant [Scaffold]s.
///
/// This class provides APIs for showing snack bars.
///
/// To display a snack bar, obtain the [ScaffoldMessengerState] for the current
/// [BuildContext] via [ScaffoldMessenger.of] and use the
/// [ScaffoldMessengerState.showSnackBar] function.
///
/// See also:
///
/// * [SnackBar], which is a temporary notification typically shown near the
/// bottom of the app using the [ScaffoldMessengerState.showSnackBar] method.
/// * Cookbook: [Display a snackbar](https://flutter.dev/docs/cookbook/design/snackbars)
class
ScaffoldMessenger
extends
StatefulWidget
{
/// Creates a widget that manages [SnackBar]s for [Scaffold] descendants.
const
ScaffoldMessenger
({
Key
key
,
@required
this
.
child
,
})
:
assert
(
child
!=
null
),
super
(
key:
key
);
/// The widget below this widget in the tree.
///
/// {@macro flutter.widgets.child}
final
Widget
child
;
/// The state from the closest instance of this class that encloses the given
/// context.
///
/// {@tool dartpad --template=stateless_widget_scaffold_center}
/// Typical usage of the [ScaffoldMessenger.of] function is to call it in
/// response to a user gesture or an application state change.
///
/// ```dart
/// Widget build(BuildContext context) {
/// return ElevatedButton(
/// child: const Text('SHOW A SNACKBAR'),
/// onPressed: () {
/// ScaffoldMessenger.of(context).showSnackBar(
/// const SnackBar(
/// content: Text('Have a snack!'),
/// ),
/// );
/// },
/// );
/// }
/// ```
/// {@end-tool}
///
/// A less elegant but more expedient solution is assign a [GlobalKey] to the
/// [ScaffoldMessenger], then use the `key.currentState` property to obtain the
/// [ScaffoldMessengerState] rather than using the [ScaffoldMessenger.of]
/// function. The [MaterialApp.scaffoldMessengerKey] refers to the root
/// ScaffoldMessenger that is provided by default.
///
/// {@tool dartpad --template=freeform}
/// Sometimes [SnackBar]s are produced by code that doesn't have ready access
/// to a valid [BuildContext]. One such example of this is when you may want
/// to show a SnackBar from a method outside of the `build` function. In these
/// cases, you can assign a [GlobalKey] to the [ScaffoldMessenger]. This
/// example shows a key being used to obtain the [ScaffoldMessengerState]
/// provided by the [MaterialApp].
///
/// ```dart imports
/// import 'package:flutter/material.dart';
/// ```
/// ```dart
/// void main() => runApp(MyApp());
///
/// class MyApp extends StatefulWidget {
/// @override
/// _MyAppState createState() => _MyAppState();
/// }
///
/// class _MyAppState extends State<MyApp> {
/// final GlobalKey<ScaffoldMessengerState> _scaffoldMessengerKey = GlobalKey<ScaffoldMessengerState>();
/// int _counter = 0;
///
/// void _incrementCounter() {
/// setState(() {
/// _counter++;
/// });
/// if (_counter % 10 == 0) {
/// _scaffoldMessengerKey.currentState.showSnackBar(const SnackBar(
/// content: Text('A multiple of ten!'),
/// ));
/// }
/// }
///
/// @override
/// Widget build(BuildContext context) {
/// return MaterialApp(
/// scaffoldMessengerKey: _scaffoldMessengerKey,
/// home: Scaffold(
/// appBar: AppBar(title: Text('ScaffoldMessenger Demo')),
/// body: Center(
/// child: Column(
/// mainAxisAlignment: MainAxisAlignment.center,
/// children: <Widget>[
/// Text(
/// 'You have pushed the button this many times:',
/// ),
/// Text(
/// '$_counter',
/// style: Theme.of(context).textTheme.headline4,
/// ),
/// ],
/// ),
/// ),
/// floatingActionButton: FloatingActionButton(
/// onPressed: _incrementCounter,
/// tooltip: 'Increment',
/// child: Icon(Icons.add),
/// ),
/// ),
/// );
/// }
/// }
///
/// ```
/// {@end-tool}
///
/// If there is no [ScaffoldMessenger] in scope, then this will throw an
/// exception.
static
ScaffoldMessengerState
of
(
BuildContext
context
)
{
assert
(
context
!=
null
);
final
_ScaffoldMessengerScope
scope
=
context
.
dependOnInheritedWidgetOfExactType
<
_ScaffoldMessengerScope
>();
return
scope
?.
_scaffoldMessengerState
;
}
@override
ScaffoldMessengerState
createState
()
=>
ScaffoldMessengerState
();
}
/// State for a [ScaffoldMessenger].
///
/// A [ScaffoldMessengerState] object can be used to [showSnackBar] for every
/// registered [Scaffold] that is a descendant of the associated
/// [ScaffoldMessenger]. Scaffolds will register to receive [SnackBar]s from
/// their closest ScaffoldMessenger ancestor.
///
/// Typically obtained via [ScaffoldMessenger.of].
class
ScaffoldMessengerState
extends
State
<
ScaffoldMessenger
>
with
TickerProviderStateMixin
{
final
LinkedHashSet
<
ScaffoldState
>
_scaffolds
=
LinkedHashSet
<
ScaffoldState
>();
final
Queue
<
ScaffoldFeatureController
<
SnackBar
,
SnackBarClosedReason
>>
_snackBars
=
Queue
<
ScaffoldFeatureController
<
SnackBar
,
SnackBarClosedReason
>>();
AnimationController
_snackBarController
;
Timer
_snackBarTimer
;
bool
_accessibleNavigation
;
@override
void
didChangeDependencies
()
{
final
MediaQueryData
mediaQuery
=
MediaQuery
.
of
(
context
);
// If we transition from accessible navigation to non-accessible navigation
// and there is a SnackBar that would have timed out that has already
// completed its timer, dismiss that SnackBar. If the timer hasn't finished
// yet, let it timeout as normal.
if
(
_accessibleNavigation
==
true
&&
!
mediaQuery
.
accessibleNavigation
&&
_snackBarTimer
!=
null
&&
!
_snackBarTimer
.
isActive
)
{
hideCurrentSnackBar
(
reason:
SnackBarClosedReason
.
timeout
);
}
_accessibleNavigation
=
mediaQuery
.
accessibleNavigation
;
super
.
didChangeDependencies
();
}
void
_register
(
ScaffoldState
scaffold
)
{
_scaffolds
.
add
(
scaffold
);
if
(
_snackBars
.
isNotEmpty
)
{
scaffold
.
_updateSnackBar
();
}
}
void
_unregister
(
ScaffoldState
scaffold
)
{
final
bool
removed
=
_scaffolds
.
remove
(
scaffold
);
// ScaffoldStates should only be removed once.
assert
(
removed
);
}
/// Shows a [SnackBar] across all registered [Scaffold]s.
///
/// A scaffold can show at most one snack bar at a time. If this function is
/// called while another snack bar is already visible, the given snack bar
/// will be added to a queue and displayed after the earlier snack bars have
/// closed.
///
/// To control how long a [SnackBar] remains visible, use [SnackBar.duration].
///
/// To remove the [SnackBar] with an exit animation, use [hideCurrentSnackBar]
/// or call [ScaffoldFeatureController.close] on the returned
/// [ScaffoldFeatureController]. To remove a [SnackBar] suddenly (without an
/// animation), use [removeCurrentSnackBar].
///
/// See [ScaffoldMessenger.of] for information about how to obtain the
/// [ScaffoldMessengerState].
///
/// {@tool dartpad --template=stateless_widget_scaffold_center}
///
/// Here is an example of showing a [SnackBar] when the user presses a button.
///
/// ```dart
/// Widget build(BuildContext context) {
/// return OutlinedButton(
/// onPressed: () {
/// ScaffoldMessenger.of(context).showSnackBar(
/// const SnackBar(
/// content: Text('A SnackBar has been shown.'),
/// ),
/// );
/// },
/// child: const Text('Show SnackBar'),
/// );
/// }
/// ```
/// {@end-tool}
ScaffoldFeatureController
<
SnackBar
,
SnackBarClosedReason
>
showSnackBar
(
SnackBar
snackBar
)
{
_snackBarController
??=
SnackBar
.
createAnimationController
(
vsync:
this
)
..
addStatusListener
(
_handleStatusChanged
);
if
(
_snackBars
.
isEmpty
)
{
assert
(
_snackBarController
.
isDismissed
);
_snackBarController
.
forward
();
}
ScaffoldFeatureController
<
SnackBar
,
SnackBarClosedReason
>
controller
;
controller
=
ScaffoldFeatureController
<
SnackBar
,
SnackBarClosedReason
>.
_
(
// We provide a fallback key so that if back-to-back snackbars happen to
// match in structure, material ink splashes and highlights don't survive
// from one to the next.
snackBar
.
withAnimation
(
_snackBarController
,
fallbackKey:
UniqueKey
()),
Completer
<
SnackBarClosedReason
>(),
()
{
assert
(
_snackBars
.
first
==
controller
);
hideCurrentSnackBar
(
reason:
SnackBarClosedReason
.
hide
);
},
null
,
// SnackBar doesn't use a builder function so setState() wouldn't rebuild it
);
setState
(()
{
_snackBars
.
addLast
(
controller
);
});
_updateScaffolds
();
return
controller
;
}
void
_handleStatusChanged
(
AnimationStatus
status
)
{
switch
(
status
)
{
case
AnimationStatus
.
dismissed
:
assert
(
_snackBars
.
isNotEmpty
);
setState
(()
{
_snackBars
.
removeFirst
();
});
_updateScaffolds
();
if
(
_snackBars
.
isNotEmpty
)
{
_snackBarController
.
forward
();
}
break
;
case
AnimationStatus
.
completed
:
setState
(()
{
assert
(
_snackBarTimer
==
null
);
// build will create a new timer if necessary to dismiss the snackBar.
});
_updateScaffolds
();
break
;
case
AnimationStatus
.
forward
:
break
;
case
AnimationStatus
.
reverse
:
break
;
}
}
void
_updateScaffolds
()
{
for
(
final
ScaffoldState
scaffold
in
_scaffolds
)
{
scaffold
.
_updateSnackBar
();
}
}
/// Removes the current [SnackBar] (if any) immediately from registered
/// [Scaffold]s.
///
/// The removed snack bar does not run its normal exit animation. If there are
/// any queued snack bars, they begin their entrance animation immediately.
void
removeCurrentSnackBar
({
SnackBarClosedReason
reason
=
SnackBarClosedReason
.
remove
})
{
assert
(
reason
!=
null
);
if
(
_snackBars
.
isEmpty
)
return
;
final
Completer
<
SnackBarClosedReason
>
completer
=
_snackBars
.
first
.
_completer
;
if
(!
completer
.
isCompleted
)
completer
.
complete
(
reason
);
_snackBarTimer
?.
cancel
();
_snackBarTimer
=
null
;
// This will trigger the animation's status callback.
_snackBarController
.
value
=
0.0
;
}
/// Removes the current [SnackBar] by running its normal exit animation.
///
/// The closed completer is called after the animation is complete.
void
hideCurrentSnackBar
({
SnackBarClosedReason
reason
=
SnackBarClosedReason
.
hide
})
{
assert
(
reason
!=
null
);
if
(
_snackBars
.
isEmpty
||
_snackBarController
.
status
==
AnimationStatus
.
dismissed
)
return
;
final
Completer
<
SnackBarClosedReason
>
completer
=
_snackBars
.
first
.
_completer
;
if
(
_accessibleNavigation
)
{
_snackBarController
.
value
=
0.0
;
completer
.
complete
(
reason
);
}
else
{
_snackBarController
.
reverse
().
then
<
void
>((
void
value
)
{
assert
(
mounted
);
if
(!
completer
.
isCompleted
)
completer
.
complete
(
reason
);
});
}
_snackBarTimer
?.
cancel
();
_snackBarTimer
=
null
;
}
@override
Widget
build
(
BuildContext
context
)
{
assert
(
debugCheckHasMediaQuery
(
context
));
final
MediaQueryData
mediaQuery
=
MediaQuery
.
of
(
context
);
_accessibleNavigation
=
mediaQuery
.
accessibleNavigation
;
if
(
_snackBars
.
isNotEmpty
)
{
final
ModalRoute
<
dynamic
>
route
=
ModalRoute
.
of
(
context
);
if
(
route
==
null
||
route
.
isCurrent
)
{
if
(
_snackBarController
.
isCompleted
&&
_snackBarTimer
==
null
)
{
final
SnackBar
snackBar
=
_snackBars
.
first
.
_widget
;
_snackBarTimer
=
Timer
(
snackBar
.
duration
,
()
{
assert
(
_snackBarController
.
status
==
AnimationStatus
.
forward
||
_snackBarController
.
status
==
AnimationStatus
.
completed
);
// Look up MediaQuery again in case the setting changed.
final
MediaQueryData
mediaQuery
=
MediaQuery
.
of
(
context
);
if
(
mediaQuery
.
accessibleNavigation
&&
snackBar
.
action
!=
null
)
return
;
hideCurrentSnackBar
(
reason:
SnackBarClosedReason
.
timeout
);
});
}
}
}
return
_ScaffoldMessengerScope
(
scaffoldMessengerState:
this
,
child:
widget
.
child
,
);
}
@override
void
dispose
()
{
_snackBarController
?.
dispose
();
_snackBarTimer
?.
cancel
();
_snackBarTimer
=
null
;
super
.
dispose
();
}
}
class
_ScaffoldMessengerScope
extends
InheritedWidget
{
const
_ScaffoldMessengerScope
({
Key
key
,
Widget
child
,
ScaffoldMessengerState
scaffoldMessengerState
,
})
:
_scaffoldMessengerState
=
scaffoldMessengerState
,
super
(
key:
key
,
child:
child
);
final
ScaffoldMessengerState
_scaffoldMessengerState
;
@override
bool
updateShouldNotify
(
_ScaffoldMessengerScope
old
)
=>
_scaffoldMessengerState
!=
old
.
_scaffoldMessengerState
;
}
/// The geometry of the [Scaffold] after all its contents have been laid out
/// except the [FloatingActionButton].
///
...
...
@@ -1204,11 +837,11 @@ class _FloatingActionButtonTransitionState extends State<_FloatingActionButtonTr
/// Implements the basic material design visual layout structure.
///
/// This class provides APIs for showing drawers and bottom sheets.
/// This class provides APIs for showing drawers
, snack bars,
and bottom sheets.
///
/// To display a persistent bottom sheet, obtain the
/// To display a
snackbar or a
persistent bottom sheet, obtain the
/// [ScaffoldState] for the current [BuildContext] via [Scaffold.of] and use the
/// [ScaffoldState.show
BottomSheet] function
.
/// [ScaffoldState.show
SnackBar] and [ScaffoldState.showBottomSheet] functions
.
///
/// {@tool dartpad --template=stateful_widget_material}
/// This example shows a [Scaffold] with a [body] and [FloatingActionButton].
...
...
@@ -1285,7 +918,7 @@ class _FloatingActionButtonTransitionState extends State<_FloatingActionButtonTr
/// Widget build(BuildContext context) {
/// return Scaffold(
/// appBar: AppBar(
/// title:
const
Text('Sample Code'),
/// title: Text('Sample Code'),
/// ),
/// body: Center(
/// child: Text('You have pressed the button $_count times.'),
...
...
@@ -1373,6 +1006,8 @@ class _FloatingActionButtonTransitionState extends State<_FloatingActionButtonTr
/// * [BottomNavigationBar], which is a horizontal array of buttons typically
/// shown along the bottom of the app using the [bottomNavigationBar]
/// property.
/// * [SnackBar], which is a temporary notification typically shown near the
/// bottom of the app using the [ScaffoldState.showSnackBar] method.
/// * [BottomSheet], which is an overlay typically shown near the bottom of the
/// app. A bottom sheet can either be persistent, in which case it is shown
/// using the [ScaffoldState.showBottomSheet] method, or modal, in which case
...
...
@@ -1380,6 +1015,7 @@ class _FloatingActionButtonTransitionState extends State<_FloatingActionButtonTr
/// * [ScaffoldState], which is the state associated with this widget.
/// * <https://material.io/design/layout/responsive-layout-grid.html>
/// * Cookbook: [Add a Drawer to a screen](https://flutter.dev/docs/cookbook/design/drawer)
/// * Cookbook: [Display a snackbar](https://flutter.dev/docs/cookbook/design/snackbars)
/// * See our
/// [Scaffold Sample Apps](https://flutter.dev/docs/catalog/samples/Scaffold).
class
Scaffold
extends
StatefulWidget
{
...
...
@@ -1751,7 +1387,7 @@ class Scaffold extends StatefulWidget {
/// ),
/// home: Scaffold(
/// body: MyScaffoldBody(),
/// appBar: AppBar(title:
const
Text('Scaffold.of Example')),
/// appBar: AppBar(title: Text('Scaffold.of Example')),
/// ),
/// color: Colors.white,
/// );
...
...
@@ -1765,32 +1401,14 @@ class Scaffold extends StatefulWidget {
/// Widget build(BuildContext context) {
/// return Center(
/// child: ElevatedButton(
/// child:
const Text('SHOW BOTTOM SHEET
'),
/// child:
Text('SHOW A SNACKBAR
'),
/// onPressed: () {
/// Scaffold.of(context).showBottomSheet<void>(
/// (BuildContext context) {
/// return Container(
/// alignment: Alignment.center,
/// height: 200,
/// color: Colors.amber,
/// child: Center(
/// child: Column(
/// mainAxisSize: MainAxisSize.min,
/// children: <Widget>[
/// const Text('BottomSheet'),
/// ElevatedButton(
/// child: const Text('Close BottomSheet'),
/// onPressed: () {
/// Navigator.pop(context);
/// },
/// )
/// ],
/// ),
/// Scaffold.of(context).showSnackBar(
/// SnackBar(
/// content: Text('Have a snack!'),
/// ),
/// );
/// },
/// );
/// },
/// ),
/// );
/// }
...
...
@@ -1809,38 +1427,20 @@ class Scaffold extends StatefulWidget {
/// ```dart
/// Widget build(BuildContext context) {
/// return Scaffold(
/// appBar: AppBar(title: const Text('Demo')),
/// appBar: AppBar(
/// title: Text('Demo')
/// ),
/// body: Builder(
/// // Create an inner BuildContext so that the onPressed methods
/// // can refer to the Scaffold with Scaffold.of().
/// builder: (BuildContext context) {
/// return Center(
/// child: ElevatedButton(
/// child:
const Text('SHOW BOTTOM SHEET
'),
/// child:
Text('SHOW A SNACKBAR
'),
/// onPressed: () {
/// Scaffold.of(context).showBottomSheet<void>(
/// (BuildContext context) {
/// return Container(
/// alignment: Alignment.center,
/// height: 200,
/// color: Colors.amber,
/// child: Center(
/// child: Column(
/// mainAxisSize: MainAxisSize.min,
/// children: <Widget>[
/// const Text('BottomSheet'),
/// ElevatedButton(
/// child: const Text('Close BottomSheet'),
/// onPressed: () {
/// Navigator.pop(context);
/// },
/// )
/// ],
/// ),
/// ),
/// );
/// },
/// );
/// Scaffold.of(context).showSnackBar(SnackBar(
/// content: Text('Have a snack!'),
/// ));
/// },
/// ),
/// );
...
...
@@ -1957,7 +1557,7 @@ class Scaffold extends StatefulWidget {
/// See also:
///
/// * [Scaffold.of], which provides access to the [ScaffoldState] object as a
/// whole, from which you can show bottom sheets, and so forth.
/// whole, from which you can show
snackbars,
bottom sheets, and so forth.
static
bool
hasDrawer
(
BuildContext
context
,
{
bool
registerForUpdates
=
true
})
{
assert
(
registerForUpdates
!=
null
);
assert
(
context
!=
null
);
...
...
@@ -1976,8 +1576,8 @@ class Scaffold extends StatefulWidget {
/// State for a [Scaffold].
///
/// Can display [
BottomSheet]s. Retrieve a [ScaffoldState] from the current
/// [BuildContext] using [Scaffold.of].
/// Can display [
SnackBar]s and [BottomSheet]s. Retrieve a [ScaffoldState] from
///
the current
[BuildContext] using [Scaffold.of].
class
ScaffoldState
extends
State
<
Scaffold
>
with
TickerProviderStateMixin
{
// DRAWER API
...
...
@@ -2068,10 +1668,12 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin {
// SNACKBAR API
ScaffoldMessengerState
_scaffoldMessenger
;
final
Queue
<
ScaffoldFeatureController
<
SnackBar
,
SnackBarClosedReason
>>
_snackBars
=
Queue
<
ScaffoldFeatureController
<
SnackBar
,
SnackBarClosedReason
>>();
AnimationController
_snackBarController
;
Timer
_snackBarTimer
;
bool
_accessibleNavigation
;
/// [ScaffoldMessengerState.showSnackBar] shows a [SnackBar] at the bottom of
/// the scaffold. This method should not be used.
/// Shows a [SnackBar] at the bottom of the scaffold.
///
/// A scaffold can show at most one snack bar at a time. If this function is
/// called while another snack bar is already visible, the given snack bar
...
...
@@ -2080,14 +1682,12 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin {
///
/// To control how long a [SnackBar] remains visible, use [SnackBar.duration].
///
/// To remove the [SnackBar] with an exit animation, use
/// [ScaffoldMessengerState.hideCurrentSnackBar] or call
/// [ScaffoldFeatureController.close] on the returned [ScaffoldFeatureController].
/// To remove a [SnackBar] suddenly (without an animation), use
/// [ScaffoldMessengerState.removeCurrentSnackBar].
/// To remove the [SnackBar] with an exit animation, use [hideCurrentSnackBar]
/// or call [ScaffoldFeatureController.close] on the returned
/// [ScaffoldFeatureController]. To remove a [SnackBar] suddenly (without an
/// animation), use [removeCurrentSnackBar].
///
/// See [ScaffoldMessenger.of] for information about how to obtain the
/// [ScaffoldMessengerState].
/// See [Scaffold.of] for information about how to obtain the [ScaffoldState].
///
/// {@tool dartpad --template=stateless_widget_scaffold_center}
///
...
...
@@ -2097,66 +1697,104 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin {
/// Widget build(BuildContext context) {
/// return OutlinedButton(
/// onPressed: () {
/// Scaffold
Messenger
.of(context).showSnackBar(
/// Scaffold.of(context).showSnackBar(
/// SnackBar(
/// content:
const
Text('A SnackBar has been shown.'),
/// content: Text('A SnackBar has been shown.'),
/// ),
/// );
/// },
/// child:
const
Text('Show SnackBar'),
/// child: Text('Show SnackBar'),
/// );
/// }
/// ```
/// {@end-tool}
///
/// See also:
///
/// * [ScaffoldMessenger], this should be used instead to manage [SnackBar]s.
// TODO(Piinks): Deprecate after customers are migrated
ScaffoldFeatureController
<
SnackBar
,
SnackBarClosedReason
>
showSnackBar
(
SnackBar
snackbar
)
{
assert
(
debugCheckHasScaffoldMessenger
(
context
));
return
_scaffoldMessenger
.
showSnackBar
(
snackbar
);
_snackBarController
??=
SnackBar
.
createAnimationController
(
vsync:
this
)
..
addStatusListener
(
_handleSnackBarStatusChange
);
if
(
_snackBars
.
isEmpty
)
{
assert
(
_snackBarController
.
isDismissed
);
_snackBarController
.
forward
();
}
ScaffoldFeatureController
<
SnackBar
,
SnackBarClosedReason
>
controller
;
controller
=
ScaffoldFeatureController
<
SnackBar
,
SnackBarClosedReason
>.
_
(
// We provide a fallback key so that if back-to-back snackbars happen to
// match in structure, material ink splashes and highlights don't survive
// from one to the next.
snackbar
.
withAnimation
(
_snackBarController
,
fallbackKey:
UniqueKey
()),
Completer
<
SnackBarClosedReason
>(),
()
{
assert
(
_snackBars
.
first
==
controller
);
hideCurrentSnackBar
(
reason:
SnackBarClosedReason
.
hide
);
},
null
,
// SnackBar doesn't use a builder function so setState() wouldn't rebuild it
);
setState
(()
{
_snackBars
.
addLast
(
controller
);
});
return
controller
;
}
/// [ScaffoldMessengerState.removeCurrentSnackBar] removes the current
/// [SnackBar] (if any) immediately. This method should not be used.
void
_handleSnackBarStatusChange
(
AnimationStatus
status
)
{
switch
(
status
)
{
case
AnimationStatus
.
dismissed
:
assert
(
_snackBars
.
isNotEmpty
);
setState
(()
{
_snackBars
.
removeFirst
();
});
if
(
_snackBars
.
isNotEmpty
)
_snackBarController
.
forward
();
break
;
case
AnimationStatus
.
completed
:
setState
(()
{
assert
(
_snackBarTimer
==
null
);
// build will create a new timer if necessary to dismiss the snack bar
});
break
;
case
AnimationStatus
.
forward
:
case
AnimationStatus
.
reverse
:
break
;
}
}
/// Removes the current [SnackBar] (if any) immediately.
///
/// The removed snack bar does not run its normal exit animation. If there are
/// any queued snack bars, they begin their entrance animation immediately.
///
/// See also:
///
/// * [ScaffoldMessenger], this should be used instead to manage [SnackBar]s.
// TODO(Piinks): Deprecate after customers are migrated
void
removeCurrentSnackBar
({
SnackBarClosedReason
reason
=
SnackBarClosedReason
.
remove
})
{
assert
(
debugCheckHasScaffoldMessenger
(
context
));
_scaffoldMessenger
.
removeCurrentSnackBar
(
reason:
reason
);
assert
(
reason
!=
null
);
if
(
_snackBars
.
isEmpty
)
return
;
final
Completer
<
SnackBarClosedReason
>
completer
=
_snackBars
.
first
.
_completer
;
if
(!
completer
.
isCompleted
)
completer
.
complete
(
reason
);
_snackBarTimer
?.
cancel
();
_snackBarTimer
=
null
;
_snackBarController
.
value
=
0.0
;
}
/// [ScaffoldMessengerState.hideCurrentSnackBar] removes the current
/// [SnackBar] by running its normal exit animation. This method should not be
/// used.
/// Removes the current [SnackBar] by running its normal exit animation.
///
/// The closed completer is called after the animation is complete.
///
/// See also:
///
/// * [ScaffoldMessenger], this should be used instead to manage [SnackBar]s.
// TODO(Piinks): Deprecate after customers are migrated.
void
hideCurrentSnackBar
({
SnackBarClosedReason
reason
=
SnackBarClosedReason
.
hide
})
{
assert
(
debugCheckHasScaffoldMessenger
(
context
));
_scaffoldMessenger
.
hideCurrentSnackBar
(
reason:
reason
);
}
ScaffoldFeatureController
<
SnackBar
,
SnackBarClosedReason
>
_snackBar
;
void
_updateSnackBar
()
{
setState
(()
{
_snackBar
=
_scaffoldMessenger
.
_snackBars
.
isNotEmpty
?
_scaffoldMessenger
.
_snackBars
.
first
:
null
;
assert
(
reason
!=
null
);
if
(
_snackBars
.
isEmpty
||
_snackBarController
.
status
==
AnimationStatus
.
dismissed
)
return
;
final
MediaQueryData
mediaQuery
=
MediaQuery
.
of
(
context
);
final
Completer
<
SnackBarClosedReason
>
completer
=
_snackBars
.
first
.
_completer
;
if
(
mediaQuery
.
accessibleNavigation
)
{
_snackBarController
.
value
=
0.0
;
completer
.
complete
(
reason
);
}
else
{
_snackBarController
.
reverse
().
then
<
void
>((
void
value
)
{
assert
(
mounted
);
if
(!
completer
.
isCompleted
)
completer
.
complete
(
reason
);
});
}
_snackBarTimer
?.
cancel
();
_snackBarTimer
=
null
;
}
// PERSISTENT BOTTOM SHEET API
...
...
@@ -2378,9 +2016,7 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin {
/// const Text('BottomSheet'),
/// ElevatedButton(
/// child: const Text('Close BottomSheet'),
/// onPressed: () {
/// Navigator.pop(context);
/// }
/// onPressed: () => Navigator.pop(context),
/// )
/// ],
/// ),
...
...
@@ -2568,14 +2204,27 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin {
@override
void
didChangeDependencies
()
{
_scaffoldMessenger
=
ScaffoldMessenger
.
of
(
context
);
_scaffoldMessenger
?.
_register
(
this
);
final
MediaQueryData
mediaQuery
=
MediaQuery
.
of
(
context
);
// If we transition from accessible navigation to non-accessible navigation
// and there is a SnackBar that would have timed out that has already
// completed its timer, dismiss that SnackBar. If the timer hasn't finished
// yet, let it timeout as normal.
if
(
_accessibleNavigation
==
true
&&
!
mediaQuery
.
accessibleNavigation
&&
_snackBarTimer
!=
null
&&
!
_snackBarTimer
.
isActive
)
{
hideCurrentSnackBar
(
reason:
SnackBarClosedReason
.
timeout
);
}
_accessibleNavigation
=
mediaQuery
.
accessibleNavigation
;
_maybeBuildPersistentBottomSheet
();
super
.
didChangeDependencies
();
}
@override
void
dispose
()
{
_snackBarController
?.
dispose
();
_snackBarTimer
?.
cancel
();
_snackBarTimer
=
null
;
_geometryNotifier
.
dispose
();
for
(
final
_StandardBottomSheet
bottomSheet
in
_dismissedBottomSheets
)
{
bottomSheet
.
animationController
?.
dispose
();
...
...
@@ -2585,7 +2234,6 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin {
}
_floatingActionButtonMoveController
.
dispose
();
_floatingActionButtonVisibilityController
.
dispose
();
_scaffoldMessenger
?.
_unregister
(
this
);
super
.
dispose
();
}
...
...
@@ -2699,6 +2347,28 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin {
final
MediaQueryData
mediaQuery
=
MediaQuery
.
of
(
context
);
final
ThemeData
themeData
=
Theme
.
of
(
context
);
final
TextDirection
textDirection
=
Directionality
.
of
(
context
);
_accessibleNavigation
=
mediaQuery
.
accessibleNavigation
;
if
(
_snackBars
.
isNotEmpty
)
{
final
ModalRoute
<
dynamic
>
route
=
ModalRoute
.
of
(
context
);
if
(
route
==
null
||
route
.
isCurrent
)
{
if
(
_snackBarController
.
isCompleted
&&
_snackBarTimer
==
null
)
{
final
SnackBar
snackBar
=
_snackBars
.
first
.
_widget
;
_snackBarTimer
=
Timer
(
snackBar
.
duration
,
()
{
assert
(
_snackBarController
.
status
==
AnimationStatus
.
forward
||
_snackBarController
.
status
==
AnimationStatus
.
completed
);
// Look up MediaQuery again in case the setting changed.
final
MediaQueryData
mediaQuery
=
MediaQuery
.
of
(
context
);
if
(
mediaQuery
.
accessibleNavigation
&&
snackBar
.
action
!=
null
)
return
;
hideCurrentSnackBar
(
reason:
SnackBarClosedReason
.
timeout
);
});
}
}
else
{
_snackBarTimer
?.
cancel
();
_snackBarTimer
=
null
;
}
}
final
List
<
LayoutId
>
children
=
<
LayoutId
>[];
_addIfNonNull
(
...
...
@@ -2753,16 +2423,16 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin {
bool
isSnackBarFloating
=
false
;
double
snackBarWidth
;
if
(
_snackBar
!=
null
)
{
final
SnackBarBehavior
snackBarBehavior
=
_snackBar
.
_widget
.
behavior
if
(
_snackBar
s
.
isNotEmpty
)
{
final
SnackBarBehavior
snackBarBehavior
=
_snackBar
s
.
first
.
_widget
.
behavior
??
themeData
.
snackBarTheme
.
behavior
??
SnackBarBehavior
.
fixed
;
isSnackBarFloating
=
snackBarBehavior
==
SnackBarBehavior
.
floating
;
snackBarWidth
=
_snackBar
.
_widget
.
width
;
snackBarWidth
=
_snackBar
s
.
first
.
_widget
.
width
;
_addIfNonNull
(
children
,
_snackBar
.
_widget
,
_snackBar
s
.
first
.
_widget
,
_ScaffoldSlot
.
snackBar
,
removeLeftPadding:
false
,
removeTopPadding:
true
,
...
...
@@ -2926,8 +2596,7 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin {
/// An interface for controlling a feature of a [Scaffold].
///
/// Commonly obtained from [ScaffoldMessengerState.showSnackBar] or
/// [ScaffoldState.showBottomSheet].
/// Commonly obtained from [ScaffoldState.showSnackBar] or [ScaffoldState.showBottomSheet].
class
ScaffoldFeatureController
<
T
extends
Widget
,
U
>
{
const
ScaffoldFeatureController
.
_
(
this
.
_widget
,
this
.
_completer
,
this
.
close
,
this
.
setState
);
final
T
_widget
;
...
...
packages/flutter/lib/src/material/snack_bar.dart
View file @
13860a7d
...
...
@@ -32,7 +32,7 @@ const Curve _snackBarFadeOutCurve = Interval(0.72, 1.0, curve: Curves.fastOutSlo
/// Specify how a [SnackBar] was closed.
///
/// The [Scaffold
Messenger
State.showSnackBar] function returns a
/// The [ScaffoldState.showSnackBar] function returns a
/// [ScaffoldFeatureController]. The value of the controller's closed property
/// is a Future that resolves to a SnackBarClosedReason. Applications that need
/// to know how a snackbar was closed can use this value.
...
...
@@ -40,7 +40,7 @@ const Curve _snackBarFadeOutCurve = Interval(0.72, 1.0, curve: Curves.fastOutSlo
/// Example:
///
/// ```dart
/// Scaffold
Messenger
.of(context).showSnackBar(
/// Scaffold.of(context).showSnackBar(
/// SnackBar( ... )
/// ).closed.then((SnackBarClosedReason reason) {
/// ...
...
...
@@ -57,10 +57,10 @@ enum SnackBarClosedReason {
swipe
,
/// The snack bar was closed by the [ScaffoldFeatureController] close callback
/// or by calling [Scaffold
Messenger
State.hideCurrentSnackBar] directly.
/// or by calling [ScaffoldState.hideCurrentSnackBar] directly.
hide
,
/// The snack bar was closed by an call to [Scaffold
Messenger
State.removeCurrentSnackBar].
/// The snack bar was closed by an call to [ScaffoldState.removeCurrentSnackBar].
remove
,
/// The snack bar was closed because its timer expired.
...
...
@@ -123,7 +123,7 @@ class _SnackBarActionState extends State<SnackBarAction> {
_haveTriggeredAction
=
true
;
});
widget
.
onPressed
();
Scaffold
Messenger
.
of
(
context
).
hideCurrentSnackBar
(
reason:
SnackBarClosedReason
.
action
);
Scaffold
.
of
(
context
).
hideCurrentSnackBar
(
reason:
SnackBarClosedReason
.
action
);
}
@override
...
...
@@ -146,8 +146,8 @@ class _SnackBarActionState extends State<SnackBarAction> {
///
/// {@youtube 560 315 https://www.youtube.com/watch?v=zpO6n_oZWw0}
///
/// To display a snack bar, call `Scaffold
Messenger.of(context).showSnackBar()`,
///
passing
an instance of [SnackBar] that describes the message.
/// To display a snack bar, call `Scaffold
.of(context).showSnackBar()`, passing
/// an instance of [SnackBar] that describes the message.
///
/// To control how long the [SnackBar] remains visible, specify a [duration].
///
...
...
@@ -156,11 +156,11 @@ class _SnackBarActionState extends State<SnackBarAction> {
///
/// See also:
///
/// * [Scaffold
Messenger.of], to obtain the current [ScaffoldMessengerState],
///
which manages the
display and animation of snack bars.
/// * [Scaffold
Messenger
State.showSnackBar], which displays a [SnackBar].
/// * [Scaffold
MessengerState.removeCurrentSnackBar], which abruptly hides the
///
currently
displayed snack bar, if any, and allows the next to be displayed.
/// * [Scaffold
.of], to obtain the current [ScaffoldState], which manages the
/// display and animation of snack bars.
/// * [ScaffoldState.showSnackBar], which displays a [SnackBar].
/// * [Scaffold
State.removeCurrentSnackBar], which abruptly hides the currently
/// displayed snack bar, if any, and allows the next to be displayed.
/// * [SnackBarAction], which is used to specify an [action] button to show
/// on the snack bar.
/// * [SnackBarThemeData], to configure the default property values for
...
...
@@ -289,7 +289,7 @@ class SnackBar extends StatefulWidget {
///
/// See also:
///
/// * [Scaffold
Messenger
State.removeCurrentSnackBar], which abruptly hides the
/// * [ScaffoldState.removeCurrentSnackBar], which abruptly hides the
/// currently displayed snack bar, if any, and allows the next to be
/// displayed.
/// * <https://material.io/design/components/snackbars.html>
...
...
@@ -301,7 +301,7 @@ class SnackBar extends StatefulWidget {
/// Called the first time that the snackbar is visible within a [Scaffold].
final
VoidCallback
onVisible
;
// API for Scaffold
MessengerState
.showSnackBar():
// API for Scaffold.showSnackBar():
/// Creates an animation controller useful for driving a snack bar's entrance and exit animation.
static
AnimationController
createAnimationController
({
@required
TickerProvider
vsync
})
{
...
...
@@ -516,14 +516,14 @@ class _SnackBarState extends State<SnackBar> {
container:
true
,
liveRegion:
true
,
onDismiss:
()
{
Scaffold
Messenger
.
of
(
context
).
removeCurrentSnackBar
(
reason:
SnackBarClosedReason
.
dismiss
);
Scaffold
.
of
(
context
).
removeCurrentSnackBar
(
reason:
SnackBarClosedReason
.
dismiss
);
},
child:
Dismissible
(
key:
const
Key
(
'dismissible'
),
direction:
DismissDirection
.
down
,
resizeDuration:
null
,
onDismissed:
(
DismissDirection
direction
)
{
Scaffold
Messenger
.
of
(
context
).
removeCurrentSnackBar
(
reason:
SnackBarClosedReason
.
swipe
);
Scaffold
.
of
(
context
).
removeCurrentSnackBar
(
reason:
SnackBarClosedReason
.
swipe
);
},
child:
snackBar
,
),
...
...
@@ -550,9 +550,7 @@ class _SnackBarState extends State<SnackBar> {
child:
snackBar
,
);
}
return
Hero
(
child:
ClipRect
(
child:
snackBarTransition
),
tag:
'<SnackBar Hero tag -
${widget.content}
>'
,
);
return
ClipRect
(
child:
snackBarTransition
);
}
}
packages/flutter/lib/src/widgets/animated_list.dart
View file @
13860a7d
...
...
@@ -512,7 +512,6 @@ class AnimatedListState extends State<AnimatedList> with TickerProviderStateMixi
/// class _SliverAnimatedListSampleState extends State<SliverAnimatedListSample> {
/// final GlobalKey<SliverAnimatedListState> _listKey = GlobalKey<SliverAnimatedListState>();
/// final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
/// final GlobalKey<ScaffoldMessengerState> _scaffoldMessengerKey = GlobalKey<ScaffoldMessengerState>();
/// ListModel<int> _list;
/// int _selectedItem;
/// int _nextItem; // The next item inserted when the user presses the '+' button.
...
...
@@ -570,7 +569,7 @@ class AnimatedListState extends State<AnimatedList> with TickerProviderStateMixi
/// _selectedItem = null;
/// });
/// } else {
/// _scaffold
Messenger
Key.currentState.showSnackBar(SnackBar(
/// _scaffoldKey.currentState.showSnackBar(SnackBar(
/// content: Text(
/// 'Select an item to remove from the list.',
/// style: TextStyle(fontSize: 20),
...
...
@@ -582,7 +581,6 @@ class AnimatedListState extends State<AnimatedList> with TickerProviderStateMixi
/// @override
/// Widget build(BuildContext context) {
/// return MaterialApp(
/// scaffoldMessengerKey: _scaffoldMessengerKey,
/// home: Scaffold(
/// key: _scaffoldKey,
/// body: CustomScrollView(
...
...
packages/flutter/lib/src/widgets/framework.dart
View file @
13860a7d
...
...
@@ -2084,7 +2084,7 @@ typedef ElementVisitor = void Function(Element element);
/// widget can be used: the build context passed to the [Builder.builder]
/// callback will be that of the [Builder] itself.
///
/// For example, in the following snippet, the [ScaffoldState.show
BottomSheet
]
/// For example, in the following snippet, the [ScaffoldState.show
SnackBar
]
/// method is called on the [Scaffold] widget that the build method itself
/// creates. If a [Builder] had not been used, and instead the `context`
/// argument of the build method itself had been used, no [Scaffold] would have
...
...
@@ -2101,32 +2101,13 @@ typedef ElementVisitor = void Function(Element element);
/// return TextButton(
/// child: Text('BUTTON'),
/// onPressed: () {
/// Scaffold.of(context).showBottomSheet<void>(
/// (BuildContext context) {
/// return Container(
/// alignment: Alignment.center,
/// height: 200,
/// color: Colors.amber,
/// child: Center(
/// child: Column(
/// mainAxisSize: MainAxisSize.min,
/// children: <Widget>[
/// const Text('BottomSheet'),
/// ElevatedButton(
/// child: const Text('Close BottomSheet'),
/// onPressed: () {
/// Navigator.pop(context),
/// },
/// )
/// ],
/// ),
/// ),
/// );
/// },
/// );
/// },
/// // here, Scaffold.of(context) returns the locally created Scaffold
/// Scaffold.of(context).showSnackBar(SnackBar(
/// content: Text('Hello.')
/// ));
/// }
/// );
///
},
///
}
/// )
/// );
/// }
...
...
packages/flutter/test/material/debug_test.dart
View file @
13860a7d
...
...
@@ -164,8 +164,6 @@ void main() {
' _InheritedTheme
\n
'
' Theme
\n
'
' AnimatedTheme
\n
'
' _ScaffoldMessengerScope
\n
'
' ScaffoldMessenger
\n
'
' Builder
\n
'
' DefaultTextStyle
\n
'
' CustomPaint
\n
'
...
...
@@ -198,50 +196,4 @@ void main() {
' or WidgetsApp widget at the top of your application widget tree.
\n
'
,
));
});
testWidgets
(
'debugCheckHasScaffoldMessenger control test'
,
(
WidgetTester
tester
)
async
{
final
GlobalKey
<
ScaffoldState
>
_scaffoldKey
=
GlobalKey
<
ScaffoldState
>();
await
tester
.
pumpWidget
(
Directionality
(
textDirection:
TextDirection
.
ltr
,
child:
MediaQuery
(
data:
const
MediaQueryData
(),
child:
Scaffold
(
key:
_scaffoldKey
,
body:
Container
(),
),
),
));
FlutterError
error
;
try
{
_scaffoldKey
.
currentState
.
showSnackBar
(
const
SnackBar
(
content:
Text
(
'Something is missing here'
)));
}
on
FlutterError
catch
(
e
)
{
error
=
e
;
}
finally
{
expect
(
error
.
diagnostics
.
length
,
5
);
expect
(
error
.
diagnostics
[
2
],
isA
<
DiagnosticsProperty
<
Element
>>());
expect
(
error
.
diagnostics
[
3
],
isA
<
DiagnosticsBlock
>());
expect
(
error
.
diagnostics
[
4
].
level
,
DiagnosticLevel
.
hint
);
expect
(
error
.
diagnostics
[
4
].
toStringDeep
(),
equalsIgnoringHashCodes
(
'Typically, the ScaffoldMessenger widget is introduced by the
\n
'
'MaterialApp at the top of your application widget tree.
\n
'
,
),
);
expect
(
error
.
toStringDeep
(),
equalsIgnoringHashCodes
(
'FlutterError
\n
'
' No ScaffoldMessenger widget found.
\n
'
' Scaffold widgets require a ScaffoldMessenger widget ancestor.
\n
'
' The specific widget that could not find a ScaffoldMessenger
\n
'
' ancestor was:
\n
'
' Scaffold-[LabeledGlobalKey<ScaffoldState>#d60fa]
\n
'
' The ancestors of this widget were:
\n
'
' MediaQuery
\n
'
' Directionality
\n
'
' [root]
\n
'
' Typically, the ScaffoldMessenger widget is introduced by the
\n
'
' MaterialApp at the top of your application widget tree.
\n
'
));
}
});
}
packages/flutter/test/material/floating_action_button_location_test.dart
View file @
13860a7d
...
...
@@ -649,7 +649,7 @@ void main() {
builder:
(
BuildContext
context
)
{
return
FloatingActionButton
(
onPressed:
()
{
Scaffold
Messenger
.
of
(
context
).
showSnackBar
(
Scaffold
.
of
(
context
).
showSnackBar
(
const
SnackBar
(
content:
Text
(
'Snacky!'
)),
);
},
...
...
packages/flutter/test/material/snack_bar_test.dart
View file @
13860a7d
...
...
@@ -18,7 +18,7 @@ void main() {
builder:
(
BuildContext
context
)
{
return
GestureDetector
(
onTap:
()
{
Scaffold
Messenger
.
of
(
context
).
showSnackBar
(
const
SnackBar
(
Scaffold
.
of
(
context
).
showSnackBar
(
const
SnackBar
(
content:
Text
(
helloSnackBar
),
duration:
Duration
(
seconds:
2
),
));
...
...
@@ -64,7 +64,7 @@ void main() {
return
GestureDetector
(
onTap:
()
{
snackBarCount
+=
1
;
Scaffold
Messenger
.
of
(
context
).
showSnackBar
(
SnackBar
(
Scaffold
.
of
(
context
).
showSnackBar
(
SnackBar
(
content:
Text
(
'bar
$snackBarCount
'
),
duration:
const
Duration
(
seconds:
2
),
));
...
...
@@ -141,7 +141,7 @@ void main() {
return
GestureDetector
(
onTap:
()
{
snackBarCount
+=
1
;
lastController
=
Scaffold
Messenger
.
of
(
context
).
showSnackBar
(
SnackBar
(
lastController
=
Scaffold
.
of
(
context
).
showSnackBar
(
SnackBar
(
content:
Text
(
'bar
$snackBarCount
'
),
duration:
Duration
(
seconds:
time
),
));
...
...
@@ -225,7 +225,7 @@ void main() {
return
GestureDetector
(
onTap:
()
{
snackBarCount
+=
1
;
Scaffold
Messenger
.
of
(
context
).
showSnackBar
(
SnackBar
(
Scaffold
.
of
(
context
).
showSnackBar
(
SnackBar
(
content:
Text
(
'bar
$snackBarCount
'
),
duration:
const
Duration
(
seconds:
2
),
));
...
...
@@ -268,7 +268,7 @@ void main() {
builder:
(
BuildContext
context
)
{
return
GestureDetector
(
onTap:
()
{
Scaffold
Messenger
.
of
(
context
).
showSnackBar
(
SnackBar
(
Scaffold
.
of
(
context
).
showSnackBar
(
SnackBar
(
content:
const
Text
(
'I am a snack bar.'
),
duration:
const
Duration
(
seconds:
2
),
action:
SnackBarAction
(
...
...
@@ -309,7 +309,7 @@ void main() {
builder:
(
BuildContext
context
)
{
return
GestureDetector
(
onTap:
()
{
Scaffold
Messenger
.
of
(
context
).
showSnackBar
(
Scaffold
.
of
(
context
).
showSnackBar
(
SnackBar
(
content:
const
Text
(
'I am a snack bar.'
),
duration:
const
Duration
(
seconds:
2
),
...
...
@@ -351,7 +351,7 @@ void main() {
builder:
(
BuildContext
context
)
{
return
GestureDetector
(
onTap:
()
{
Scaffold
Messenger
.
of
(
context
).
showSnackBar
(
Scaffold
.
of
(
context
).
showSnackBar
(
SnackBar
(
content:
const
Text
(
'I am a snack bar.'
),
duration:
const
Duration
(
seconds:
2
),
...
...
@@ -389,7 +389,7 @@ void main() {
builder:
(
BuildContext
context
)
{
return
GestureDetector
(
onTap:
()
{
Scaffold
Messenger
.
of
(
context
).
showSnackBar
(
Scaffold
.
of
(
context
).
showSnackBar
(
SnackBar
(
content:
const
Text
(
'I am a snack bar.'
),
margin:
const
EdgeInsets
.
all
(
padding
),
...
...
@@ -476,7 +476,7 @@ void main() {
builder:
(
BuildContext
context
)
{
return
GestureDetector
(
onTap:
()
{
Scaffold
Messenger
.
of
(
context
).
showSnackBar
(
Scaffold
.
of
(
context
).
showSnackBar
(
const
SnackBar
(
content:
Text
(
'I am a snack bar.'
),
padding:
EdgeInsets
.
all
(
padding
),
...
...
@@ -520,7 +520,7 @@ void main() {
builder:
(
BuildContext
context
)
{
return
GestureDetector
(
onTap:
()
{
Scaffold
Messenger
.
of
(
context
).
showSnackBar
(
Scaffold
.
of
(
context
).
showSnackBar
(
SnackBar
(
content:
const
Text
(
'I am a snack bar.'
),
width:
width
,
...
...
@@ -558,7 +558,7 @@ void main() {
builder:
(
BuildContext
context
)
{
return
GestureDetector
(
onTap:
()
{
Scaffold
Messenger
.
of
(
context
).
showSnackBar
(
Scaffold
.
of
(
context
).
showSnackBar
(
SnackBar
(
content:
const
Text
(
'I am a snack bar.'
),
duration:
const
Duration
(
seconds:
2
),
...
...
@@ -611,7 +611,7 @@ void main() {
builder:
(
BuildContext
context
)
{
return
GestureDetector
(
onTap:
()
{
Scaffold
Messenger
.
of
(
context
).
showSnackBar
(
SnackBar
(
Scaffold
.
of
(
context
).
showSnackBar
(
SnackBar
(
content:
const
Text
(
'I am a snack bar.'
),
duration:
const
Duration
(
seconds:
2
),
action:
SnackBarAction
(
label:
'ACTION'
,
onPressed:
()
{
}),
...
...
@@ -666,7 +666,7 @@ void main() {
builder:
(
BuildContext
context
)
{
return
GestureDetector
(
onTap:
()
{
Scaffold
Messenger
.
of
(
context
).
showSnackBar
(
SnackBar
(
Scaffold
.
of
(
context
).
showSnackBar
(
SnackBar
(
content:
const
Text
(
'I am a snack bar.'
),
duration:
const
Duration
(
seconds:
2
),
action:
SnackBarAction
(
label:
'ACTION'
,
onPressed:
()
{}),
...
...
@@ -717,7 +717,7 @@ void main() {
builder:
(
BuildContext
context
)
{
return
GestureDetector
(
onTap:
()
{
Scaffold
Messenger
.
of
(
context
).
showSnackBar
(
SnackBar
(
Scaffold
.
of
(
context
).
showSnackBar
(
SnackBar
(
content:
const
Text
(
'I am a snack bar.'
),
duration:
const
Duration
(
seconds:
2
),
action:
SnackBarAction
(
label:
'ACTION'
,
onPressed:
()
{}),
...
...
@@ -771,7 +771,7 @@ void main() {
builder:
(
BuildContext
context
)
{
return
GestureDetector
(
onTap:
()
{
Scaffold
Messenger
.
of
(
context
).
showSnackBar
(
SnackBar
(
Scaffold
.
of
(
context
).
showSnackBar
(
SnackBar
(
content:
const
Text
(
'I am a snack bar.'
),
duration:
const
Duration
(
seconds:
2
),
action:
SnackBarAction
(
label:
'ACTION'
,
onPressed:
()
{}),
...
...
@@ -829,7 +829,7 @@ void main() {
builder:
(
BuildContext
context
)
{
return
GestureDetector
(
onTap:
()
{
Scaffold
Messenger
.
of
(
context
).
showSnackBar
(
SnackBar
(
Scaffold
.
of
(
context
).
showSnackBar
(
SnackBar
(
content:
const
Text
(
'I am a snack bar.'
),
duration:
const
Duration
(
seconds:
2
),
action:
SnackBarAction
(
label:
'ACTION'
,
onPressed:
()
{}),
...
...
@@ -861,18 +861,18 @@ void main() {
});
testWidgets
(
'SnackBarClosedReason'
,
(
WidgetTester
tester
)
async
{
final
GlobalKey
<
Scaffold
MessengerState
>
scaffoldMessengerKey
=
GlobalKey
<
ScaffoldMessenger
State
>();
final
GlobalKey
<
Scaffold
State
>
scaffoldKey
=
GlobalKey
<
Scaffold
State
>();
bool
actionPressed
=
false
;
SnackBarClosedReason
closedReason
;
await
tester
.
pumpWidget
(
MaterialApp
(
scaffoldMessengerKey:
scaffoldMessengerKey
,
home:
Scaffold
(
key:
scaffoldKey
,
body:
Builder
(
builder:
(
BuildContext
context
)
{
return
GestureDetector
(
onTap:
()
{
Scaffold
Messenger
.
of
(
context
).
showSnackBar
(
SnackBar
(
Scaffold
.
of
(
context
).
showSnackBar
(
SnackBar
(
content:
const
Text
(
'snack'
),
duration:
const
Duration
(
seconds:
2
),
action:
SnackBarAction
(
...
...
@@ -917,14 +917,14 @@ void main() {
// Pop up the snack bar and then remove it.
await
tester
.
tap
(
find
.
text
(
'X'
));
await
tester
.
pump
(
const
Duration
(
milliseconds:
750
));
scaffold
Messenger
Key
.
currentState
.
removeCurrentSnackBar
();
scaffoldKey
.
currentState
.
removeCurrentSnackBar
();
await
tester
.
pumpAndSettle
(
const
Duration
(
seconds:
1
));
expect
(
closedReason
,
equals
(
SnackBarClosedReason
.
remove
));
// Pop up the snack bar and then hide it.
await
tester
.
tap
(
find
.
text
(
'X'
));
await
tester
.
pump
(
const
Duration
(
milliseconds:
750
));
scaffold
Messenger
Key
.
currentState
.
hideCurrentSnackBar
();
scaffoldKey
.
currentState
.
hideCurrentSnackBar
();
await
tester
.
pumpAndSettle
(
const
Duration
(
seconds:
1
));
expect
(
closedReason
,
equals
(
SnackBarClosedReason
.
hide
));
...
...
@@ -944,14 +944,13 @@ void main() {
await
tester
.
pumpWidget
(
MaterialApp
(
home:
MediaQuery
(
data:
const
MediaQueryData
(
accessibleNavigation:
true
),
child:
ScaffoldMessenger
(
child:
Builder
(
builder:
(
BuildContext
context
)
{
return
Scaffold
(
child:
Scaffold
(
key:
scaffoldKey
,
body:
GestureDetector
(
body:
Builder
(
builder:
(
BuildContext
context
)
{
return
GestureDetector
(
onTap:
()
{
ScaffoldMessenger
.
of
(
context
).
showSnackBar
(
SnackBar
(
Scaffold
.
of
(
context
).
showSnackBar
(
SnackBar
(
content:
const
Text
(
'snack'
),
duration:
const
Duration
(
seconds:
1
),
action:
SnackBarAction
(
...
...
@@ -961,10 +960,9 @@ void main() {
));
},
child:
const
Text
(
'X'
),
),
);
}
)
}
,
)
,
),
),
));
...
...
@@ -988,13 +986,13 @@ void main() {
await
tester
.
pumpWidget
(
MaterialApp
(
home:
MediaQuery
(
data:
const
MediaQueryData
(
accessibleNavigation:
true
),
child:
ScaffoldMessenger
(
child:
Builder
(
builder:
(
BuildContext
context
)
{
return
Scaffold
(
child:
Scaffold
(
key:
scaffoldKey
,
body:
GestureDetector
(
body:
Builder
(
builder:
(
BuildContext
context
)
{
return
GestureDetector
(
onTap:
()
{
ScaffoldMessenger
.
of
(
context
).
showSnackBar
(
SnackBar
(
Scaffold
.
of
(
context
).
showSnackBar
(
SnackBar
(
content:
const
Text
(
'snack'
),
duration:
const
Duration
(
seconds:
1
),
action:
SnackBarAction
(
...
...
@@ -1004,11 +1002,11 @@ void main() {
));
},
child:
const
Text
(
'X'
),
),
);
}),
},
),
),
),
)
));
await
tester
.
tap
(
find
.
text
(
'X'
));
await
tester
.
pumpAndSettle
();
...
...
@@ -1033,7 +1031,7 @@ void main() {
builder:
(
BuildContext
context
)
{
return
GestureDetector
(
onTap:
()
{
Scaffold
Messenger
.
of
(
context
).
showSnackBar
(
const
SnackBar
(
Scaffold
.
of
(
context
).
showSnackBar
(
const
SnackBar
(
content:
Text
(
helloSnackBar
),
));
},
...
...
@@ -1082,7 +1080,7 @@ void main() {
builder:
(
BuildContext
context
)
{
return
GestureDetector
(
onTap:
()
{
Scaffold
Messenger
.
of
(
context
).
showSnackBar
(
SnackBar
(
Scaffold
.
of
(
context
).
showSnackBar
(
SnackBar
(
content:
const
Text
(
'test'
),
action:
SnackBarAction
(
label:
'foo'
,
onPressed:
()
{
}),
));
...
...
@@ -1128,7 +1126,7 @@ void main() {
builder:
(
BuildContext
context
)
{
return
GestureDetector
(
onTap:
()
{
Scaffold
Messenger
.
of
(
context
).
showSnackBar
(
SnackBar
(
Scaffold
.
of
(
context
).
showSnackBar
(
SnackBar
(
content:
Text
(
nonconst
(
'hello'
)),
duration:
null
,
));
...
...
@@ -1158,7 +1156,7 @@ void main() {
builder:
(
BuildContext
context
)
{
return
GestureDetector
(
onTap:
()
{
Scaffold
Messenger
.
of
(
context
).
showSnackBar
(
SnackBar
(
Scaffold
.
of
(
context
).
showSnackBar
(
SnackBar
(
content:
const
Text
(
'hello'
),
duration:
const
Duration
(
seconds:
1
),
onVisible:
()
{
...
...
@@ -1195,14 +1193,14 @@ void main() {
builder:
(
BuildContext
context
)
{
return
GestureDetector
(
onTap:
()
{
Scaffold
Messenger
.
of
(
context
).
showSnackBar
(
SnackBar
(
Scaffold
.
of
(
context
).
showSnackBar
(
SnackBar
(
content:
const
Text
(
'hello'
),
duration:
const
Duration
(
seconds:
1
),
onVisible:
()
{
called
+=
1
;
},
));
Scaffold
Messenger
.
of
(
context
).
showSnackBar
(
SnackBar
(
Scaffold
.
of
(
context
).
showSnackBar
(
SnackBar
(
content:
const
Text
(
'hello 2'
),
duration:
const
Duration
(
seconds:
1
),
onVisible:
()
{
...
...
@@ -1249,8 +1247,8 @@ void main() {
),
);
final
Scaffold
MessengerState
scaffoldMessengerState
=
tester
.
state
(
find
.
byType
(
ScaffoldMessenger
));
scaffold
Messenger
State
.
showSnackBar
(
snackBar
);
final
Scaffold
State
scaffoldState
=
tester
.
state
(
find
.
byType
(
Scaffold
));
scaffoldState
.
showSnackBar
(
snackBar
);
await
tester
.
pumpAndSettle
();
// Have the SnackBar fully animate out.
...
...
@@ -1280,8 +1278,8 @@ void main() {
),
);
final
Scaffold
MessengerState
scaffoldMessengerState
=
tester
.
state
(
find
.
byType
(
ScaffoldMessenger
));
scaffold
Messenger
State
.
showSnackBar
(
snackBar
);
final
Scaffold
State
scaffoldState
=
tester
.
state
(
find
.
byType
(
Scaffold
));
scaffoldState
.
showSnackBar
(
snackBar
);
await
tester
.
pumpAndSettle
();
// Have the SnackBar fully animate out.
...
...
@@ -1300,8 +1298,9 @@ void main() {
testWidgets
(
'Padding of
$behavior
is not consumed by viewInsets'
,
(
WidgetTester
tester
)
async
{
final
Widget
child
=
MaterialApp
(
home:
Scaffold
(
final
Widget
child
=
Directionality
(
textDirection:
TextDirection
.
ltr
,
child:
Scaffold
(
resizeToAvoidBottomInset:
false
,
floatingActionButton:
FloatingActionButton
(
child:
const
Icon
(
Icons
.
send
),
...
...
@@ -1311,7 +1310,7 @@ void main() {
builder:
(
BuildContext
context
)
{
return
GestureDetector
(
onTap:
()
{
Scaffold
Messenger
.
of
(
context
).
showSnackBar
(
Scaffold
.
of
(
context
).
showSnackBar
(
SnackBar
(
content:
const
Text
(
'I am a snack bar.'
),
duration:
const
Duration
(
seconds:
2
),
...
...
@@ -1375,8 +1374,8 @@ void main() {
),
);
final
Scaffold
MessengerState
scaffoldMessengerState
=
tester
.
state
(
find
.
byType
(
ScaffoldMessenger
));
scaffold
Messenger
State
.
showSnackBar
(
final
Scaffold
State
scaffoldState
=
tester
.
state
(
find
.
byType
(
Scaffold
));
scaffoldState
.
showSnackBar
(
const
SnackBar
(
content:
Text
(
'Snackbar text'
),
behavior:
SnackBarBehavior
.
fixed
,
...
...
@@ -1411,7 +1410,7 @@ void main() {
builder:
(
BuildContext
context
)
{
return
GestureDetector
(
onTap:
()
{
Scaffold
Messenger
.
of
(
context
).
showSnackBar
(
SnackBar
(
Scaffold
.
of
(
context
).
showSnackBar
(
SnackBar
(
content:
const
Text
(
'I am a snack bar.'
),
duration:
const
Duration
(
seconds:
2
),
action:
SnackBarAction
(
label:
'ACTION'
,
onPressed:
()
{}),
...
...
@@ -1453,8 +1452,8 @@ void main() {
),
);
final
Scaffold
MessengerState
scaffoldMessengerState
=
tester
.
state
(
find
.
byType
(
ScaffoldMessenger
));
scaffold
Messenger
State
.
showSnackBar
(
final
Scaffold
State
scaffoldState
=
tester
.
state
(
find
.
byType
(
Scaffold
));
scaffoldState
.
showSnackBar
(
const
SnackBar
(
content:
Text
(
'SnackBar text'
),
behavior:
SnackBarBehavior
.
fixed
,
...
...
@@ -1490,8 +1489,8 @@ void main() {
),
);
final
Scaffold
MessengerState
scaffoldMessengerState
=
tester
.
state
(
find
.
byType
(
ScaffoldMessenger
));
scaffold
Messenger
State
.
showSnackBar
(
final
Scaffold
State
scaffoldState
=
tester
.
state
(
find
.
byType
(
Scaffold
));
scaffoldState
.
showSnackBar
(
const
SnackBar
(
content:
Text
(
'SnackBar text'
),
behavior:
SnackBarBehavior
.
floating
,
...
...
@@ -1507,74 +1506,4 @@ void main() {
},
);
});
testWidgets
(
'SnackBars hero across transitions'
,
(
WidgetTester
tester
)
async
{
const
String
snackBarText
=
'hello snackbar'
;
const
String
firstHeader
=
'home'
;
const
String
secondHeader
=
'second'
;
const
Key
snackTarget
=
Key
(
'snack-target'
);
const
Key
transitionTarget
=
Key
(
'transition-target'
);
Widget
_buildApp
()
{
return
MaterialApp
(
routes:
<
String
,
WidgetBuilder
>
{
'/'
:
(
BuildContext
context
)
{
return
Scaffold
(
appBar:
AppBar
(
title:
const
Text
(
firstHeader
)),
body:
Center
(
child:
ElevatedButton
(
key:
transitionTarget
,
child:
const
Text
(
'PUSH'
),
onPressed:
()
{
Navigator
.
of
(
context
).
pushNamed
(
'/second'
);
},
),
),
floatingActionButton:
FloatingActionButton
(
key:
snackTarget
,
onPressed:
()
async
{
ScaffoldMessenger
.
of
(
context
).
showSnackBar
(
const
SnackBar
(
content:
Text
(
snackBarText
),
),
);
},
child:
const
Text
(
'X'
),
),
);
},
'/second'
:
(
BuildContext
context
)
=>
Scaffold
(
appBar:
AppBar
(
title:
const
Text
(
secondHeader
)),
),
}
);
}
await
tester
.
pumpWidget
(
_buildApp
());
expect
(
find
.
text
(
snackBarText
),
findsNothing
);
expect
(
find
.
text
(
firstHeader
),
findsOneWidget
);
expect
(
find
.
text
(
secondHeader
),
findsNothing
);
// Present SnackBar
await
tester
.
tap
(
find
.
byKey
(
snackTarget
));
await
tester
.
pump
();
// schedule animation
expect
(
find
.
text
(
snackBarText
),
findsOneWidget
);
await
tester
.
pump
();
// begin animation
expect
(
find
.
text
(
snackBarText
),
findsOneWidget
);
await
tester
.
pump
(
const
Duration
(
milliseconds:
750
));
expect
(
find
.
text
(
snackBarText
),
findsOneWidget
);
// Push new route
await
tester
.
tap
(
find
.
byKey
(
transitionTarget
));
await
tester
.
pump
();
expect
(
find
.
text
(
snackBarText
),
findsOneWidget
);
expect
(
find
.
text
(
firstHeader
),
findsOneWidget
);
expect
(
find
.
text
(
secondHeader
,
skipOffstage:
false
),
findsOneWidget
);
await
tester
.
pump
();
expect
(
find
.
text
(
snackBarText
),
findsOneWidget
);
expect
(
find
.
text
(
firstHeader
),
findsOneWidget
);
expect
(
find
.
text
(
secondHeader
),
findsOneWidget
);
await
tester
.
pump
(
const
Duration
(
milliseconds:
750
));
expect
(
find
.
text
(
snackBarText
),
findsOneWidget
);
expect
(
find
.
text
(
firstHeader
),
findsNothing
);
expect
(
find
.
text
(
secondHeader
),
findsOneWidget
);
});
}
packages/flutter/test/material/snack_bar_theme_test.dart
View file @
13860a7d
...
...
@@ -73,7 +73,7 @@ void main() {
builder:
(
BuildContext
context
)
{
return
GestureDetector
(
onTap:
()
{
Scaffold
Messenger
.
of
(
context
).
showSnackBar
(
SnackBar
(
Scaffold
.
of
(
context
).
showSnackBar
(
SnackBar
(
content:
const
Text
(
text
),
duration:
const
Duration
(
seconds:
2
),
action:
SnackBarAction
(
label:
'ACTION'
,
onPressed:
()
{}),
...
...
@@ -110,7 +110,7 @@ void main() {
builder:
(
BuildContext
context
)
{
return
GestureDetector
(
onTap:
()
{
Scaffold
Messenger
.
of
(
context
).
showSnackBar
(
SnackBar
(
Scaffold
.
of
(
context
).
showSnackBar
(
SnackBar
(
content:
const
Text
(
text
),
duration:
const
Duration
(
seconds:
2
),
action:
SnackBarAction
(
label:
'ACTION'
,
onPressed:
()
{}),
...
...
@@ -153,7 +153,7 @@ void main() {
builder:
(
BuildContext
context
)
{
return
GestureDetector
(
onTap:
()
{
Scaffold
Messenger
.
of
(
context
).
showSnackBar
(
SnackBar
(
Scaffold
.
of
(
context
).
showSnackBar
(
SnackBar
(
backgroundColor:
backgroundColor
,
elevation:
elevation
,
shape:
shape
,
...
...
@@ -200,7 +200,7 @@ void main() {
builder:
(
BuildContext
context
)
{
return
GestureDetector
(
onTap:
()
{
Scaffold
Messenger
.
of
(
context
).
showSnackBar
(
SnackBar
(
Scaffold
.
of
(
context
).
showSnackBar
(
SnackBar
(
content:
const
Text
(
'I am a snack bar.'
),
duration:
const
Duration
(
seconds:
2
),
action:
SnackBarAction
(
label:
'ACTION'
,
onPressed:
()
{}),
...
...
@@ -242,7 +242,7 @@ void main() {
builder:
(
BuildContext
context
)
{
return
GestureDetector
(
onTap:
()
{
Scaffold
Messenger
.
of
(
context
).
showSnackBar
(
SnackBar
(
Scaffold
.
of
(
context
).
showSnackBar
(
SnackBar
(
content:
const
Text
(
'I am a snack bar.'
),
duration:
const
Duration
(
seconds:
2
),
action:
SnackBarAction
(
label:
'ACTION'
,
onPressed:
()
{}),
...
...
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