Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
d608e4a
ScaffoldMessenger
Piinks Aug 26, 2020
8f7593c
Remove unintended changes
Piinks Aug 26, 2020
6e784ab
Fix sample
Piinks Aug 26, 2020
20d8afd
++
Piinks Aug 26, 2020
d9f57e3
Apply suggestions from code review
Piinks Aug 26, 2020
063e159
Update docs
Piinks Aug 27, 2020
c4632bd
Review feedback
Piinks Aug 28, 2020
843e287
Sample app
Piinks Aug 28, 2020
2042863
Merge branch 'master' of github.com:flutter/flutter into scaffoldMess…
Piinks Aug 31, 2020
e3cd0d7
Fix sample code
Piinks Aug 31, 2020
72469cd
Review feedback
Piinks Sep 3, 2020
3626dc3
Merge branch 'master' of github.com:flutter/flutter into scaffoldMess…
Piinks Sep 23, 2020
c04ffa1
Update to re-land
Piinks Sep 23, 2020
a475e3f
More test
Piinks Sep 23, 2020
0c1373b
Fix analyzer for deprecation.
Piinks Sep 23, 2020
30981fc
Review feedback
Piinks Sep 24, 2020
a667729
Analyzer
Piinks Sep 24, 2020
739b0e2
Re-trigger build
Piinks Sep 24, 2020
ac6a955
++
Piinks Sep 24, 2020
3117436
Merge branch 'master' of github.com:flutter/flutter into scaffoldMess…
Piinks Sep 24, 2020
587dc5b
Analyzer again
Piinks Sep 24, 2020
43bd2ea
Re-work for untouched SnackBar classes
Piinks Sep 25, 2020
aa1d646
Tidying
Piinks Sep 25, 2020
c552f47
Add nullOk for .of, + tests
Piinks Oct 5, 2020
df692db
Analyzer
Piinks Oct 5, 2020
5216711
Merge branch 'master' of github.com:flutter/flutter into scaffoldMess…
Piinks Oct 5, 2020
ef5d262
Merge branch 'master' of github.com:flutter/flutter into scaffoldMess…
Piinks Oct 5, 2020
6ce0413
Update packages/flutter/lib/src/material/scaffold.dart
Piinks Oct 5, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 35 additions & 21 deletions packages/flutter/lib/src/material/app.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import 'floating_action_button.dart';
import 'icons.dart';
import 'material_localizations.dart';
import 'page.dart';
import 'scaffold.dart' show ScaffoldMessenger, ScaffoldMessengerState;
import 'theme.dart';

/// [MaterialApp] uses this [TextStyle] as its [DefaultTextStyle] to encourage
Expand Down Expand Up @@ -166,6 +167,7 @@ class MaterialApp extends StatefulWidget {
const MaterialApp({
Key? key,
this.navigatorKey,
this.scaffoldMessengerKey,
this.home,
this.routes = const <String, WidgetBuilder>{},
this.initialRoute,
Expand Down Expand Up @@ -214,6 +216,7 @@ 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,
Expand Down Expand Up @@ -263,6 +266,14 @@ 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;

Expand Down Expand Up @@ -724,27 +735,30 @@ class _MaterialAppState extends State<MaterialApp> {
}
theme ??= widget.theme ?? ThemeData.light();

return AnimatedTheme(
data: theme,
isMaterialAppTheme: true,
child: widget.builder != null
? Builder(
builder: (BuildContext context) {
// Why are we surrounding a builder with a builder?
//
// The widget.builder may contain code that invokes
// Theme.of(), which should return the theme we selected
// above in AnimatedTheme. However, if we invoke
// widget.builder() directly as the child of AnimatedTheme
// then there is no Context separating them, and the
// widget.builder() will not find the theme. Therefore, we
// surround widget.builder with yet another builder so that
// a context separates them and Theme.of() correctly
// resolves to the theme we passed to AnimatedTheme.
return widget.builder!(context, child);
},
)
: child!,
return ScaffoldMessenger(
key: widget.scaffoldMessengerKey,
child: AnimatedTheme(
data: theme,
isMaterialAppTheme: true,
child: widget.builder != null
? Builder(
builder: (BuildContext context) {
// Why are we surrounding a builder with a builder?
//
// The widget.builder may contain code that invokes
// Theme.of(), which should return the theme we selected
// above in AnimatedTheme. However, if we invoke
// widget.builder() directly as the child of AnimatedTheme
// then there is no Context separating them, and the
// widget.builder() will not find the theme. Therefore, we
// surround widget.builder with yet another builder so that
// a context separates them and Theme.of() correctly
// resolves to the theme we passed to AnimatedTheme.
return widget.builder!(context, child);
},
)
: child!,
)
);
}

Expand Down
2 changes: 1 addition & 1 deletion packages/flutter/lib/src/material/app_bar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ class _ToolbarContainerLayout extends SingleChildLayoutDelegate {
/// icon: const Icon(Icons.add_alert),
/// tooltip: 'Show Snackbar',
/// onPressed: () {
/// scaffoldKey.currentState.showSnackBar(snackBar);
/// ScaffoldMessenger.of(context).showSnackBar(snackBar);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't the of call return null if there's no messenger in the tree?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It can, but in this case it there is a MaterialApp above in the sample code, so it has a ScaffoldMessenger by default.

/// },
/// ),
/// IconButton(
Expand Down
33 changes: 32 additions & 1 deletion packages/flutter/lib/src/material/debug.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import 'package:flutter/widgets.dart';

import 'material.dart';
import 'material_localizations.dart';
import 'scaffold.dart' show Scaffold;
import 'scaffold.dart' show Scaffold, ScaffoldMessenger;

/// Asserts that the given context has a [Material] ancestor.
///
Expand Down Expand Up @@ -123,3 +123,34 @@ 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.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;
}
Loading