Unverified Commit 81439922 authored by Alexandre Ardhuin's avatar Alexandre Ardhuin Committed by GitHub

migrate some material files to nullsafety (#67078)

* migrate some material files to nullsafety

* review
parent 371667ec
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:developer' show Timeline, Flow;
import 'dart:io' show Platform;
......@@ -123,7 +121,7 @@ class AboutListTile extends StatelessWidget {
/// derived from the nearest [Title] widget. The version, icon, and legalese
/// values default to the empty string.
const AboutListTile({
Key key,
Key? key,
this.icon,
this.child,
this.applicationName,
......@@ -140,13 +138,13 @@ class AboutListTile extends StatelessWidget {
///
/// This is not necessarily the same as the image shown in the dialog box
/// itself; which is controlled by the [applicationIcon] property.
final Widget icon;
final Widget? icon;
/// The label to show on this drawer item.
///
/// Defaults to a text widget that says "About Foo" where "Foo" is the
/// application name specified by [applicationName].
final Widget child;
final Widget? child;
/// The name of the application.
///
......@@ -155,14 +153,14 @@ class AboutListTile extends StatelessWidget {
///
/// Defaults to the value of [Title.title], if a [Title] widget can be found.
/// Otherwise, defaults to [Platform.resolvedExecutable].
final String applicationName;
final String? applicationName;
/// The version of this build of the application.
///
/// This string is shown under the application name in the [AboutDialog].
///
/// Defaults to the empty string.
final String applicationVersion;
final String? applicationVersion;
/// The icon to show next to the application name in the [AboutDialog].
///
......@@ -173,14 +171,14 @@ class AboutListTile extends StatelessWidget {
///
/// This is not necessarily the same as the icon shown on the drawer item
/// itself, which is controlled by the [icon] property.
final Widget applicationIcon;
final Widget? applicationIcon;
/// A string to show in small print in the [AboutDialog].
///
/// Typically this is a copyright notice.
///
/// Defaults to the empty string.
final String applicationLegalese;
final String? applicationLegalese;
/// Widgets to add to the [AboutDialog] after the name, version, and legalese.
///
......@@ -188,14 +186,14 @@ class AboutListTile extends StatelessWidget {
/// or other information to show in the about box.
///
/// Defaults to nothing.
final List<Widget> aboutBoxChildren;
final List<Widget>? aboutBoxChildren;
/// Whether this list tile is part of a vertically dense list.
///
/// If this property is null, then its value is based on [ListTileTheme.dense].
///
/// Dense list tiles default to a smaller height.
final bool dense;
final bool? dense;
@override
Widget build(BuildContext context) {
......@@ -203,7 +201,7 @@ class AboutListTile extends StatelessWidget {
assert(debugCheckHasMaterialLocalizations(context));
return ListTile(
leading: icon,
title: child ?? Text(MaterialLocalizations.of(context).aboutListTileTitle(
title: child ?? Text(MaterialLocalizations.of(context)!.aboutListTileTitle(
applicationName ?? _defaultApplicationName(context),
)),
dense: dense,
......@@ -238,14 +236,14 @@ class AboutListTile extends StatelessWidget {
/// The [context], [useRootNavigator] and [routeSettings] arguments are passed to
/// [showDialog], the documentation for which discusses how it is used.
void showAboutDialog({
@required BuildContext context,
String applicationName,
String applicationVersion,
Widget applicationIcon,
String applicationLegalese,
List<Widget> children,
required BuildContext context,
String? applicationName,
String? applicationVersion,
Widget? applicationIcon,
String? applicationLegalese,
List<Widget>? children,
bool useRootNavigator = true,
RouteSettings routeSettings,
RouteSettings? routeSettings,
}) {
assert(context != null);
assert(useRootNavigator != null);
......@@ -285,16 +283,16 @@ void showAboutDialog({
/// The licenses shown on the [LicensePage] are those returned by the
/// [LicenseRegistry] API, which can be used to add more licenses to the list.
void showLicensePage({
@required BuildContext context,
String applicationName,
String applicationVersion,
Widget applicationIcon,
String applicationLegalese,
required BuildContext context,
String? applicationName,
String? applicationVersion,
Widget? applicationIcon,
String? applicationLegalese,
bool useRootNavigator = false,
}) {
assert(context != null);
assert(useRootNavigator != null);
Navigator.of(context, rootNavigator: useRootNavigator).push(MaterialPageRoute<void>(
Navigator.of(context, rootNavigator: useRootNavigator)!.push(MaterialPageRoute<void>(
builder: (BuildContext context) => LicensePage(
applicationName: applicationName,
applicationVersion: applicationVersion,
......@@ -330,7 +328,7 @@ class AboutDialog extends StatelessWidget {
/// derived from the nearest [Title] widget. The version, icon, and legalese
/// values default to the empty string.
const AboutDialog({
Key key,
Key? key,
this.applicationName,
this.applicationVersion,
this.applicationIcon,
......@@ -342,14 +340,14 @@ class AboutDialog extends StatelessWidget {
///
/// Defaults to the value of [Title.title], if a [Title] widget can be found.
/// Otherwise, defaults to [Platform.resolvedExecutable].
final String applicationName;
final String? applicationName;
/// The version of this build of the application.
///
/// This string is shown under the application name.
///
/// Defaults to the empty string.
final String applicationVersion;
final String? applicationVersion;
/// The icon to show next to the application name.
///
......@@ -357,14 +355,14 @@ class AboutDialog extends StatelessWidget {
///
/// Typically this will be an [ImageIcon] widget. It should honor the
/// [IconTheme]'s [IconThemeData.size].
final Widget applicationIcon;
final Widget? applicationIcon;
/// A string to show in small print.
///
/// Typically this is a copyright notice.
///
/// Defaults to the empty string.
final String applicationLegalese;
final String? applicationLegalese;
/// Widgets to add to the dialog box after the name, version, and legalese.
///
......@@ -372,30 +370,30 @@ class AboutDialog extends StatelessWidget {
/// or other information to show in the about box.
///
/// Defaults to nothing.
final List<Widget> children;
final List<Widget>? children;
@override
Widget build(BuildContext context) {
assert(debugCheckHasMaterialLocalizations(context));
final String name = applicationName ?? _defaultApplicationName(context);
final String version = applicationVersion ?? _defaultApplicationVersion(context);
final Widget icon = applicationIcon ?? _defaultApplicationIcon(context);
final Widget? icon = applicationIcon ?? _defaultApplicationIcon(context);
return AlertDialog(
content: ListBody(
children: <Widget>[
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
if (icon != null) IconTheme(data: Theme.of(context).iconTheme, child: icon),
if (icon != null) IconTheme(data: Theme.of(context)!.iconTheme, child: icon),
Expanded(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 24.0),
child: ListBody(
children: <Widget>[
Text(name, style: Theme.of(context).textTheme.headline5),
Text(version, style: Theme.of(context).textTheme.bodyText2),
Text(name, style: Theme.of(context)!.textTheme.headline5),
Text(version, style: Theme.of(context)!.textTheme.bodyText2),
const SizedBox(height: _textVerticalSeparation),
Text(applicationLegalese ?? '', style: Theme.of(context).textTheme.caption),
Text(applicationLegalese ?? '', style: Theme.of(context)!.textTheme.caption),
],
),
),
......@@ -407,7 +405,7 @@ class AboutDialog extends StatelessWidget {
),
actions: <Widget>[
TextButton(
child: Text(MaterialLocalizations.of(context).viewLicensesButtonLabel),
child: Text(MaterialLocalizations.of(context)!.viewLicensesButtonLabel),
onPressed: () {
showLicensePage(
context: context,
......@@ -419,7 +417,7 @@ class AboutDialog extends StatelessWidget {
},
),
TextButton(
child: Text(MaterialLocalizations.of(context).closeButtonLabel),
child: Text(MaterialLocalizations.of(context)!.closeButtonLabel),
onPressed: () {
Navigator.pop(context);
},
......@@ -449,7 +447,7 @@ class LicensePage extends StatefulWidget {
/// The licenses shown on the [LicensePage] are those returned by the
/// [LicenseRegistry] API, which can be used to add more licenses to the list.
const LicensePage({
Key key,
Key? key,
this.applicationName,
this.applicationVersion,
this.applicationIcon,
......@@ -460,14 +458,14 @@ class LicensePage extends StatefulWidget {
///
/// Defaults to the value of [Title.title], if a [Title] widget can be found.
/// Otherwise, defaults to [Platform.resolvedExecutable].
final String applicationName;
final String? applicationName;
/// The version of this build of the application.
///
/// This string is shown under the application name.
///
/// Defaults to the empty string.
final String applicationVersion;
final String? applicationVersion;
/// The icon to show below the application name.
///
......@@ -475,33 +473,33 @@ class LicensePage extends StatefulWidget {
///
/// Typically this will be an [ImageIcon] widget. It should honor the
/// [IconTheme]'s [IconThemeData.size].
final Widget applicationIcon;
final Widget? applicationIcon;
/// A string to show in small print.
///
/// Typically this is a copyright notice.
///
/// Defaults to the empty string.
final String applicationLegalese;
final String? applicationLegalese;
@override
_LicensePageState createState() => _LicensePageState();
}
class _LicensePageState extends State<LicensePage> {
final ValueNotifier<int> selectedId = ValueNotifier<int>(null);
final ValueNotifier<int?> selectedId = ValueNotifier<int?>(null);
@override
Widget build(BuildContext context) {
return _MasterDetailFlow(
detailPageFABlessGutterWidth: _getGutterSize(context),
title: Text(MaterialLocalizations.of(context).licensesPageTitle),
title: Text(MaterialLocalizations.of(context)!.licensesPageTitle),
detailPageBuilder: _packageLicensePage,
masterViewBuilder: _packagesView,
);
}
Widget _packageLicensePage(BuildContext _, Object args, ScrollController scrollController) {
Widget _packageLicensePage(BuildContext _, Object? args, ScrollController? scrollController) {
assert(args is _DetailArguments);
final _DetailArguments detailArguments = args as _DetailArguments;
return _PackageLicensePage(
......@@ -528,9 +526,9 @@ class _LicensePageState extends State<LicensePage> {
class _AboutProgram extends StatelessWidget {
const _AboutProgram({
Key key,
@required this.name,
@required this.version,
Key? key,
required this.name,
required this.version,
this.icon,
this.legalese,
}) : assert(name != null),
......@@ -539,8 +537,8 @@ class _AboutProgram extends StatelessWidget {
final String name;
final String version;
final Widget icon;
final String legalese;
final Widget? icon;
final String? legalese;
@override
Widget build(BuildContext context) {
......@@ -553,26 +551,26 @@ class _AboutProgram extends StatelessWidget {
children: <Widget>[
Text(
name,
style: Theme.of(context).textTheme.headline5,
style: Theme.of(context)!.textTheme.headline5,
textAlign: TextAlign.center,
),
if (icon != null)
IconTheme(data: Theme.of(context).iconTheme, child: icon),
IconTheme(data: Theme.of(context)!.iconTheme, child: icon!),
Text(
version,
style: Theme.of(context).textTheme.bodyText2,
style: Theme.of(context)!.textTheme.bodyText2,
textAlign: TextAlign.center,
),
const SizedBox(height: _textVerticalSeparation),
Text(
legalese ?? '',
style: Theme.of(context).textTheme.caption,
style: Theme.of(context)!.textTheme.caption,
textAlign: TextAlign.center,
),
const SizedBox(height: _textVerticalSeparation),
Text(
'Powered by Flutter',
style: Theme.of(context).textTheme.bodyText2,
style: Theme.of(context)!.textTheme.bodyText2,
textAlign: TextAlign.center,
),
],
......@@ -583,17 +581,17 @@ class _AboutProgram extends StatelessWidget {
class _PackagesView extends StatefulWidget {
const _PackagesView({
Key key,
@required this.about,
@required this.isLateral,
@required this.selectedId,
Key? key,
required this.about,
required this.isLateral,
required this.selectedId,
}) : assert(about != null),
assert(isLateral != null),
super(key: key);
final Widget about;
final bool isLateral;
final ValueNotifier<int> selectedId;
final ValueNotifier<int?> selectedId;
@override
_PackagesViewState createState() => _PackagesViewState();
......@@ -617,17 +615,17 @@ class _PackagesViewState extends State<_PackagesView> {
builder: (BuildContext context, BoxConstraints constraints) {
switch (snapshot.connectionState) {
case ConnectionState.done:
_initDefaultDetailPage(snapshot.data, context);
return ValueListenableBuilder<int>(
_initDefaultDetailPage(snapshot.data!, context);
return ValueListenableBuilder<int?>(
valueListenable: widget.selectedId,
builder: (BuildContext context, int selectedId, Widget _) {
builder: (BuildContext context, int? selectedId, Widget? _) {
return Center(
child: Material(
color: Theme.of(context).cardColor,
color: Theme.of(context)!.cardColor,
elevation: 4.0,
child: Container(
constraints: BoxConstraints.loose(const Size.fromWidth(600.0)),
child: _packagesList(context, selectedId, snapshot.data, widget.isLateral),
child: _packagesList(context, selectedId, snapshot.data!, widget.isLateral),
),
),
);
......@@ -635,7 +633,7 @@ class _PackagesViewState extends State<_PackagesView> {
);
default:
return Material(
color: Theme.of(context).cardColor,
color: Theme.of(context)!.cardColor,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
......@@ -656,8 +654,8 @@ class _PackagesViewState extends State<_PackagesView> {
return;
}
final String packageName = data.packages[widget.selectedId.value ?? 0];
final List<int> bindings = data.packageLicenseBindings[packageName];
_MasterDetailFlow.of(context).setInitialDetailPage(
final List<int> bindings = data.packageLicenseBindings[packageName]!;
_MasterDetailFlow.of(context)!.setInitialDetailPage(
_DetailArguments(
packageName,
bindings.map((int i) => data.licenses[i]).toList(growable: false),
......@@ -667,7 +665,7 @@ class _PackagesViewState extends State<_PackagesView> {
Widget _packagesList(
final BuildContext context,
final int selectedId,
final int? selectedId,
final _LicenseData data,
final bool drawSelection,
) {
......@@ -680,7 +678,7 @@ class _PackagesViewState extends State<_PackagesView> {
.map<Widget>((MapEntry<int, String> entry) {
final String packageName = entry.value;
final int index = entry.key;
final List<int> bindings = data.packageLicenseBindings[packageName];
final List<int> bindings = data.packageLicenseBindings[packageName]!;
return _PackageListTile(
packageName: packageName,
index: index,
......@@ -688,7 +686,7 @@ class _PackagesViewState extends State<_PackagesView> {
numberLicenses: bindings.length,
onTap: () {
widget.selectedId.value = index;
_MasterDetailFlow.of(context).openDetailPage(_DetailArguments(
_MasterDetailFlow.of(context)!.openDetailPage(_DetailArguments(
packageName,
bindings.map((int i) => data.licenses[i]).toList(growable: false),
));
......@@ -702,27 +700,27 @@ class _PackagesViewState extends State<_PackagesView> {
class _PackageListTile extends StatelessWidget {
const _PackageListTile({
Key key,
this.packageName,
Key? key,
required this.packageName,
this.index,
this.isSelected,
this.numberLicenses,
required this.isSelected,
required this.numberLicenses,
this.onTap,
}) : super(key:key);
final String packageName;
final int index;
final int? index;
final bool isSelected;
final int numberLicenses;
final GestureTapCallback onTap;
final GestureTapCallback? onTap;
@override
Widget build(BuildContext context) {
return Ink(
color: isSelected ? Theme.of(context).highlightColor : Theme.of(context).cardColor,
color: isSelected ? Theme.of(context)!.highlightColor : Theme.of(context)!.cardColor,
child: ListTile(
title: Text(packageName),
subtitle: Text(MaterialLocalizations.of(context).licensesPackageDetailText(numberLicenses)),
subtitle: Text(MaterialLocalizations.of(context)!.licensesPackageDetailText(numberLicenses)),
selected: isSelected,
onTap: onTap,
),
......@@ -740,7 +738,7 @@ class _LicenseData {
// Special treatment for the first package since it should be the package
// for delivered application.
String firstPackage;
String? firstPackage;
void addLicense(LicenseEntry entry) {
// Before the license can be added, we must first record the packages to
......@@ -750,7 +748,7 @@ class _LicenseData {
// Bind this license to the package using the next index value. This
// creates a contract that this license must be inserted at this same
// index value.
packageLicenseBindings[package].add(licenses.length);
packageLicenseBindings[package]!.add(licenses.length);
}
licenses.add(entry); // Completion of the contract above.
}
......@@ -768,7 +766,7 @@ class _LicenseData {
/// Sort the packages using some comparison method, or by the default manner,
/// which is to put the application package first, followed by every other
/// package in case-insensitive alphabetical order.
void sortPackages([int compare(String a, String b)]) {
void sortPackages([int Function(String a, String b)? compare]) {
packages.sort(compare ?? (String a, String b) {
// Based on how LicenseRegistry currently behaves, the first package
// returned is the end user application license. This should be
......@@ -806,15 +804,15 @@ class _DetailArguments {
class _PackageLicensePage extends StatefulWidget {
const _PackageLicensePage({
Key key,
this.packageName,
this.licenseEntries,
this.scrollController,
Key? key,
required this.packageName,
required this.licenseEntries,
required this.scrollController,
}) : super(key: key);
final String packageName;
final List<LicenseEntry> licenseEntries;
final ScrollController scrollController;
final ScrollController? scrollController;
@override
_PackageLicensePageState createState() => _PackageLicensePageState();
......@@ -847,7 +845,7 @@ class _PackageLicensePageState extends State<_PackageLicensePage> {
return true;
}());
final List<LicenseParagraph> paragraphs =
await SchedulerBinding.instance.scheduleTask<List<LicenseParagraph>>(
await SchedulerBinding.instance!.scheduleTask<List<LicenseParagraph>>(
license.paragraphs.toList,
Priority.animation,
debugLabel: 'License',
......@@ -892,8 +890,8 @@ class _PackageLicensePageState extends State<_PackageLicensePage> {
@override
Widget build(BuildContext context) {
assert(debugCheckHasMaterialLocalizations(context));
final MaterialLocalizations localizations = MaterialLocalizations.of(context);
final ThemeData theme = Theme.of(context);
final MaterialLocalizations localizations = MaterialLocalizations.of(context)!;
final ThemeData? theme = Theme.of(context);
final String title = widget.packageName;
final String subtitle = localizations.licensesPackageDetailText(widget.licenseEntries.length);
final double pad = _getGutterSize(context);
......@@ -916,7 +914,7 @@ class _PackageLicensePageState extends State<_PackageLicensePage> {
title: _PackageLicensePageTitle(
title,
subtitle,
theme.appBarTheme.textTheme ?? theme.primaryTextTheme,
theme!.appBarTheme.textTheme ?? theme.primaryTextTheme,
),
),
body: Center(
......@@ -943,7 +941,7 @@ class _PackageLicensePageState extends State<_PackageLicensePage> {
SliverAppBar(
automaticallyImplyLeading: false,
pinned: true,
backgroundColor: theme.cardColor,
backgroundColor: theme!.cardColor,
title: _PackageLicensePageTitle(title, subtitle, theme.textTheme),
),
SliverPadding(
......@@ -974,7 +972,7 @@ class _PackageLicensePageTitle extends StatelessWidget {
this.title,
this.subtitle,
this.theme, {
Key key,
Key? key,
}) : super(key: key);
final String title;
......@@ -1001,7 +999,7 @@ String _defaultApplicationName(BuildContext context) {
// someone really wants their application title to change dynamically, they
// can provide an explicit applicationName to the widgets defined in this
// file, instead of relying on the default.
final Title ancestorTitle = context.findAncestorWidgetOfExactType<Title>();
final Title? ancestorTitle = context.findAncestorWidgetOfExactType<Title>();
return ancestorTitle?.title ?? Platform.resolvedExecutable.split(Platform.pathSeparator).last;
}
......@@ -1010,7 +1008,7 @@ String _defaultApplicationVersion(BuildContext context) {
return '';
}
Widget _defaultApplicationIcon(BuildContext context) {
Widget? _defaultApplicationIcon(BuildContext context) {
// TODO(ianh): Get this from the embedder somehow.
return null;
}
......@@ -1020,7 +1018,7 @@ const double _wideGutterSize = 24.0;
const double _narrowGutterSize = 12.0;
double _getGutterSize(BuildContext context) =>
MediaQuery.of(context).size.width >= _materialGutterThreshold ? _wideGutterSize : _narrowGutterSize;
MediaQuery.of(context)!.size.width >= _materialGutterThreshold ? _wideGutterSize : _narrowGutterSize;
/// Signature for the builder callback used by [_MasterDetailFlow].
typedef _MasterViewBuilder = Widget Function(BuildContext context, bool isLateralUI);
......@@ -1029,7 +1027,7 @@ typedef _MasterViewBuilder = Widget Function(BuildContext context, bool isLatera
///
/// scrollController is provided when the page destination is the draggable
/// sheet in the lateral UI. Otherwise, it is null.
typedef _DetailPageBuilder = Widget Function(BuildContext context, Object arguments, ScrollController scrollController);
typedef _DetailPageBuilder = Widget Function(BuildContext context, Object? arguments, ScrollController? scrollController);
/// Signature for the builder callback used by [_MasterDetailFlow.actionBuilder].
///
......@@ -1078,9 +1076,9 @@ class _MasterDetailFlow extends StatefulWidget {
/// Creates a master detail navigation flow which is either nested or
/// lateral depending on screen width.
const _MasterDetailFlow({
Key key,
@required this.detailPageBuilder,
@required this.masterViewBuilder,
Key? key,
required this.detailPageBuilder,
required this.masterViewBuilder,
this.actionBuilder,
this.automaticallyImplyLeading = true,
this.breakpoint,
......@@ -1113,7 +1111,7 @@ class _MasterDetailFlow extends StatefulWidget {
/// This builder is usually a wrapper around the [masterViewBuilder] builder to provide the
/// extra UI required to make a page. However, this builder is optional, and the master page
/// can be built using the master view builder and the configuration for the lateral UI's app bar.
final _MasterViewBuilder masterPageBuilder;
final _MasterViewBuilder? masterPageBuilder;
/// Builder for the detail page.
///
......@@ -1124,29 +1122,29 @@ class _MasterDetailFlow extends StatefulWidget {
final _DetailPageBuilder detailPageBuilder;
/// Override the width of the master view in the lateral UI.
final double masterViewWidth;
final double? masterViewWidth;
/// Override the width of the floating action button gutter in the lateral UI.
final double detailPageFABGutterWidth;
final double? detailPageFABGutterWidth;
/// Override the width of the gutter when there is no floating action button.
final double detailPageFABlessGutterWidth;
final double? detailPageFABlessGutterWidth;
/// Add a floating action button to the lateral UI. If no [masterPageBuilder] is supplied, this
/// floating action button is also used on the nested master page.
///
/// See [Scaffold.floatingActionButton].
final FloatingActionButton floatingActionButton;
final FloatingActionButton? floatingActionButton;
/// The title for the lateral UI [AppBar].
///
/// See [AppBar.title].
final Widget title;
final Widget? title;
/// A widget to display before the title for the lateral UI [AppBar].
///
/// See [AppBar.leading].
final Widget leading;
final Widget? leading;
/// Override the framework from determining whether to show a leading widget or not.
///
......@@ -1157,10 +1155,10 @@ class _MasterDetailFlow extends StatefulWidget {
/// app bar or not.
///
/// See [AppBar.centerTitle].
final bool centerTitle;
final bool? centerTitle;
/// See [AppBar.flexibleSpace].
final Widget flexibleSpace;
final Widget? flexibleSpace;
/// Build actions for the lateral UI, and potentially the master page in the nested UI.
///
......@@ -1171,25 +1169,25 @@ class _MasterDetailFlow extends StatefulWidget {
/// by [_MasterDetailFlow], then [_ActionLevel.composite] indicates the
/// actions are for the
/// nested master page.
final _ActionBuilder actionBuilder;
final _ActionBuilder? actionBuilder;
/// Determine where the floating action button will go.
///
/// If null, [FloatingActionButtonLocation.endTop] is used.
///
/// Also see [Scaffold.floatingActionButtonLocation].
final FloatingActionButtonLocation floatingActionButtonLocation;
final FloatingActionButtonLocation? floatingActionButtonLocation;
/// Determine where the floating action button will go on the master page.
///
/// See [Scaffold.floatingActionButtonLocation].
final FloatingActionButtonLocation floatingActionButtonMasterPageLocation;
final FloatingActionButtonLocation? floatingActionButtonMasterPageLocation;
/// Forces display mode and style.
final _LayoutMode displayMode;
/// Width at which layout changes from nested to lateral.
final double breakpoint;
final double? breakpoint;
@override
_MasterDetailFlowState createState() => _MasterDetailFlowState();
......@@ -1202,11 +1200,11 @@ class _MasterDetailFlow extends StatefulWidget {
/// ```dart
/// _MasterDetailFlow.of(context).openDetailPage(arguments);
/// ```
static _MasterDetailFlowProxy of(
static _MasterDetailFlowProxy? of(
BuildContext context, {
bool nullOk = false,
}) {
_PageOpener pageOpener = context.findAncestorStateOfType<_MasterDetailScaffoldState>();
_PageOpener? pageOpener = context.findAncestorStateOfType<_MasterDetailScaffoldState>();
pageOpener ??= context.findAncestorStateOfType<_MasterDetailFlowState>();
assert(() {
if (pageOpener == null && !nullOk) {
......@@ -1253,10 +1251,10 @@ class _MasterDetailFlowState extends State<_MasterDetailFlow> implements _PageOp
_Focus focus = _Focus.master;
/// Cache of arguments passed when opening a detail page. Used when rebuilding.
Object _cachedDetailArguments;
Object? _cachedDetailArguments;
/// Record of the layout that was built.
_LayoutMode _builtLayout;
_LayoutMode? _builtLayout;
/// Key to access navigator in the nested layout.
final GlobalKey<NavigatorState> _navigatorKey = GlobalKey<NavigatorState>();
......@@ -1265,7 +1263,7 @@ class _MasterDetailFlowState extends State<_MasterDetailFlow> implements _PageOp
void openDetailPage(Object arguments) {
_cachedDetailArguments = arguments;
if (_builtLayout == _LayoutMode.nested) {
_navigatorKey.currentState.pushNamed(_navDetail, arguments: arguments);
_navigatorKey.currentState!.pushNamed(_navDetail, arguments: arguments);
} else {
focus = _Focus.detail;
}
......@@ -1303,7 +1301,7 @@ class _MasterDetailFlowState extends State<_MasterDetailFlow> implements _PageOp
return WillPopScope(
// Push pop check into nested navigator.
onWillPop: () async => !(await _navigatorKey.currentState.maybePop()),
onWillPop: () async => !(await _navigatorKey.currentState!.maybePop()),
child: Navigator(
key: _navigatorKey,
initialRoute: 'initial',
......@@ -1343,11 +1341,11 @@ class _MasterDetailFlowState extends State<_MasterDetailFlow> implements _PageOp
return MaterialPageRoute<dynamic>(
builder: (BuildContext c) => BlockSemantics(
child: widget.masterPageBuilder != null
? widget.masterPageBuilder(c, false)
? widget.masterPageBuilder!(c, false)
: _MasterPage(
leading: widget.leading ??
(widget.automaticallyImplyLeading && Navigator.of(context).canPop()
? BackButton(onPressed: () => Navigator.of(context).pop())
(widget.automaticallyImplyLeading && Navigator.of(context)!.canPop()
? BackButton(onPressed: () => Navigator.of(context)!.pop())
: null),
title: widget.title,
centerTitle: widget.centerTitle,
......@@ -1362,13 +1360,13 @@ class _MasterDetailFlowState extends State<_MasterDetailFlow> implements _PageOp
);
}
MaterialPageRoute<void> _detailPageRoute(Object arguments) {
MaterialPageRoute<void> _detailPageRoute(Object? arguments) {
return MaterialPageRoute<dynamic>(builder: (BuildContext context) {
return WillPopScope(
onWillPop: () async {
// No need for setState() as rebuild happens on navigation pop.
focus = _Focus.master;
Navigator.of(context).pop();
Navigator.of(context)!.pop();
return false;
},
child: BlockSemantics(child: widget.detailPageBuilder(context, arguments, null)),
......@@ -1382,7 +1380,7 @@ class _MasterDetailFlowState extends State<_MasterDetailFlow> implements _PageOp
actionBuilder: widget.actionBuilder ?? (_, __) => const<Widget>[],
automaticallyImplyLeading: widget.automaticallyImplyLeading,
centerTitle: widget.centerTitle,
detailPageBuilder: (BuildContext context, Object args, ScrollController scrollController) =>
detailPageBuilder: (BuildContext context, Object? args, ScrollController? scrollController) =>
widget.detailPageBuilder(context, args ?? _cachedDetailArguments, scrollController),
floatingActionButton: widget.floatingActionButton,
detailPageFABlessGutterWidth: widget.detailPageFABlessGutterWidth,
......@@ -1399,7 +1397,7 @@ class _MasterDetailFlowState extends State<_MasterDetailFlow> implements _PageOp
class _MasterPage extends StatelessWidget {
const _MasterPage({
Key key,
Key? key,
this.leading,
this.title,
this.actionBuilder,
......@@ -1408,18 +1406,18 @@ class _MasterPage extends StatelessWidget {
this.floatingActionButton,
this.floatingActionButtonLocation,
this.masterViewBuilder,
this.automaticallyImplyLeading,
required this.automaticallyImplyLeading,
}) : super(key: key);
final _MasterViewBuilder masterViewBuilder;
final Widget title;
final Widget leading;
final _MasterViewBuilder? masterViewBuilder;
final Widget? title;
final Widget? leading;
final bool automaticallyImplyLeading;
final bool centerTitle;
final Widget flexibleSpace;
final _ActionBuilder actionBuilder;
final FloatingActionButton floatingActionButton;
final FloatingActionButtonLocation floatingActionButtonLocation;
final bool? centerTitle;
final Widget? flexibleSpace;
final _ActionBuilder? actionBuilder;
final FloatingActionButton? floatingActionButton;
final FloatingActionButtonLocation? floatingActionButtonLocation;
@override
Widget build(BuildContext context) {
......@@ -1429,12 +1427,12 @@ class _MasterPage extends StatelessWidget {
leading: leading,
actions: actionBuilder == null
? const <Widget>[]
: actionBuilder(context, _ActionLevel.composite),
: actionBuilder!(context, _ActionLevel.composite),
centerTitle: centerTitle,
flexibleSpace: flexibleSpace,
automaticallyImplyLeading: automaticallyImplyLeading,
),
body: masterViewBuilder(context, false),
body: masterViewBuilder!(context, false),
floatingActionButton: floatingActionButton,
floatingActionButtonLocation: floatingActionButtonLocation,
);
......@@ -1449,16 +1447,16 @@ const double _kDetailPageFABGutterWidth = 84.0;
class _MasterDetailScaffold extends StatefulWidget {
const _MasterDetailScaffold({
Key key,
@required this.detailPageBuilder,
@required this.masterViewBuilder,
Key? key,
required this.detailPageBuilder,
required this.masterViewBuilder,
this.actionBuilder,
this.floatingActionButton,
this.floatingActionButtonLocation,
this.initialArguments,
this.leading,
this.title,
this.automaticallyImplyLeading,
required this.automaticallyImplyLeading,
this.centerTitle,
this.detailPageFABlessGutterWidth,
this.detailPageFABGutterWidth,
......@@ -1475,17 +1473,17 @@ class _MasterDetailScaffold extends StatefulWidget {
/// that uses the [ScrollController] provided. In fact, it is strongly recommended the entire
/// lateral page is scrollable.
final _DetailPageBuilder detailPageBuilder;
final _ActionBuilder actionBuilder;
final FloatingActionButton floatingActionButton;
final FloatingActionButtonLocation floatingActionButtonLocation;
final Object initialArguments;
final Widget leading;
final Widget title;
final _ActionBuilder? actionBuilder;
final FloatingActionButton? floatingActionButton;
final FloatingActionButtonLocation? floatingActionButtonLocation;
final Object? initialArguments;
final Widget? leading;
final Widget? title;
final bool automaticallyImplyLeading;
final bool centerTitle;
final double detailPageFABlessGutterWidth;
final double detailPageFABGutterWidth;
final double masterViewWidth;
final bool? centerTitle;
final double? detailPageFABlessGutterWidth;
final double? detailPageFABGutterWidth;
final double? masterViewWidth;
@override
_MasterDetailScaffoldState createState() => _MasterDetailScaffoldState();
......@@ -1493,12 +1491,12 @@ class _MasterDetailScaffold extends StatefulWidget {
class _MasterDetailScaffoldState extends State<_MasterDetailScaffold>
implements _PageOpener {
FloatingActionButtonLocation floatingActionButtonLocation;
double detailPageFABGutterWidth;
double detailPageFABlessGutterWidth;
double masterViewWidth;
late FloatingActionButtonLocation floatingActionButtonLocation;
late double detailPageFABGutterWidth;
late double detailPageFABlessGutterWidth;
late double masterViewWidth;
final ValueNotifier<Object> _detailArguments = ValueNotifier<Object>(null);
final ValueNotifier<Object?> _detailArguments = ValueNotifier<Object?>(null);
@override
void initState() {
......@@ -1511,16 +1509,16 @@ class _MasterDetailScaffoldState extends State<_MasterDetailScaffold>
@override
void openDetailPage(Object arguments) {
SchedulerBinding.instance
SchedulerBinding.instance!
.addPostFrameCallback((_) => _detailArguments.value = arguments);
_MasterDetailFlow.of(context).openDetailPage(arguments);
_MasterDetailFlow.of(context)!.openDetailPage(arguments);
}
@override
void setInitialDetailPage(Object arguments) {
SchedulerBinding.instance
SchedulerBinding.instance!
.addPostFrameCallback((_) => _detailArguments.value = arguments);
_MasterDetailFlow.of(context).setInitialDetailPage(arguments);
_MasterDetailFlow.of(context)!.setInitialDetailPage(arguments);
}
@override
......@@ -1531,7 +1529,7 @@ class _MasterDetailScaffoldState extends State<_MasterDetailScaffold>
floatingActionButtonLocation: floatingActionButtonLocation,
appBar: AppBar(
title: widget.title,
actions: widget.actionBuilder(context, _ActionLevel.top),
actions: widget.actionBuilder!(context, _ActionLevel.top),
leading: widget.leading,
automaticallyImplyLeading: widget.automaticallyImplyLeading,
centerTitle: widget.centerTitle,
......@@ -1544,10 +1542,10 @@ class _MasterDetailScaffoldState extends State<_MasterDetailScaffold>
constraints:
BoxConstraints.tightFor(width: masterViewWidth),
child: IconTheme(
data: Theme.of(context).primaryIconTheme,
data: Theme.of(context)!.primaryIconTheme,
child: ButtonBar(
children:
widget.actionBuilder(context, _ActionLevel.view),
widget.actionBuilder!(context, _ActionLevel.view),
),
),
)
......@@ -1567,9 +1565,9 @@ class _MasterDetailScaffoldState extends State<_MasterDetailScaffold>
? detailPageFABlessGutterWidth
: detailPageFABGutterWidth,
),
child: ValueListenableBuilder<Object>(
child: ValueListenableBuilder<Object?>(
valueListenable: _detailArguments,
builder: (BuildContext context, Object value, Widget child) {
builder: (BuildContext context, Object? value, Widget? child) {
return AnimatedSwitcher(
transitionBuilder:
(Widget child, Animation<double> animation) =>
......@@ -1578,7 +1576,7 @@ class _MasterDetailScaffoldState extends State<_MasterDetailScaffold>
null, null, animation, null, child),
duration: const Duration(milliseconds: 500),
child: Container(
key: ValueKey<Object>(value ?? widget.initialArguments),
key: ValueKey<Object?>(value ?? widget.initialArguments),
constraints: const BoxConstraints.expand(),
child: _DetailView(
builder: widget.detailPageBuilder,
......@@ -1601,7 +1599,7 @@ class _MasterDetailScaffoldState extends State<_MasterDetailScaffold>
? Scaffold(
appBar: AppBar(
title: widget.title,
actions: widget.actionBuilder(context, _ActionLevel.top),
actions: widget.actionBuilder!(context, _ActionLevel.top),
leading: widget.leading,
automaticallyImplyLeading: widget.automaticallyImplyLeading,
centerTitle: widget.centerTitle,
......@@ -1615,23 +1613,23 @@ class _MasterDetailScaffoldState extends State<_MasterDetailScaffold>
class _DetailView extends StatelessWidget {
const _DetailView({
Key key,
@required _DetailPageBuilder builder,
Object arguments,
Key? key,
required _DetailPageBuilder builder,
Object? arguments,
}) : assert(builder != null),
_builder = builder,
_arguments = arguments,
super(key: key);
final _DetailPageBuilder _builder;
final Object _arguments;
final Object? _arguments;
@override
Widget build(BuildContext context) {
if (_arguments == null) {
return Container();
}
final double screenHeight = MediaQuery.of(context).size.height;
final double screenHeight = MediaQuery.of(context)!.size.height;
final double minHeight = (screenHeight - kToolbarHeight) / screenHeight;
return DraggableScrollableSheet(
......@@ -1643,7 +1641,7 @@ class _DetailView extends StatelessWidget {
return MouseRegion(
// TODO(TonicArtos): Remove MouseRegion workaround for pointer hover events passing through DraggableScrollableSheet once https://github.com/flutter/flutter/issues/59741 is resolved.
child: Card(
color: Theme.of(context).cardColor,
color: Theme.of(context)!.cardColor,
elevation: _kCardElevation,
clipBehavior: Clip.antiAlias,
margin: const EdgeInsets.fromLTRB(
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:ui' as ui;
import 'package:flutter/cupertino.dart';
......@@ -166,7 +164,7 @@ class MaterialApp extends StatefulWidget {
///
/// The boolean arguments, [routes], and [navigatorObservers], must not be null.
const MaterialApp({
Key key,
Key? key,
this.navigatorKey,
this.home,
this.routes = const <String, WidgetBuilder>{},
......@@ -215,10 +213,10 @@ class MaterialApp extends StatefulWidget {
/// Creates a [MaterialApp] that uses the [Router] instead of a [Navigator].
const MaterialApp.router({
Key key,
Key? key,
this.routeInformationProvider,
@required this.routeInformationParser,
@required this.routerDelegate,
required this.routeInformationParser,
required this.routerDelegate,
this.backButtonDispatcher,
this.builder,
this.title = '',
......@@ -263,10 +261,10 @@ class MaterialApp extends StatefulWidget {
super(key: key);
/// {@macro flutter.widgets.widgetsApp.navigatorKey}
final GlobalKey<NavigatorState> navigatorKey;
final GlobalKey<NavigatorState>? navigatorKey;
/// {@macro flutter.widgets.widgetsApp.home}
final Widget home;
final Widget? home;
/// The application's top-level routing table.
///
......@@ -276,41 +274,41 @@ class MaterialApp extends StatefulWidget {
/// an appropriate transition, including [Hero] animations, to the new route.
///
/// {@macro flutter.widgets.widgetsApp.routes}
final Map<String, WidgetBuilder> routes;
final Map<String, WidgetBuilder>? routes;
/// {@macro flutter.widgets.widgetsApp.initialRoute}
final String initialRoute;
final String? initialRoute;
/// {@macro flutter.widgets.widgetsApp.onGenerateRoute}
final RouteFactory onGenerateRoute;
final RouteFactory? onGenerateRoute;
/// {@macro flutter.widgets.widgetsApp.onGenerateInitialRoutes}
final InitialRouteListFactory onGenerateInitialRoutes;
final InitialRouteListFactory? onGenerateInitialRoutes;
/// {@macro flutter.widgets.widgetsApp.onUnknownRoute}
final RouteFactory onUnknownRoute;
final RouteFactory? onUnknownRoute;
/// {@macro flutter.widgets.widgetsApp.navigatorObservers}
final List<NavigatorObserver> navigatorObservers;
final List<NavigatorObserver>? navigatorObservers;
/// {@macro flutter.widgets.widgetsApp.routeInformationProvider}
final RouteInformationProvider routeInformationProvider;
final RouteInformationProvider? routeInformationProvider;
/// {@macro flutter.widgets.widgetsApp.routeInformationParser}
final RouteInformationParser<Object> routeInformationParser;
final RouteInformationParser<Object>? routeInformationParser;
/// {@macro flutter.widgets.widgetsApp.routerDelegate}
final RouterDelegate<Object> routerDelegate;
final RouterDelegate<Object>? routerDelegate;
/// {@macro flutter.widgets.widgetsApp.backButtonDispatcher}
final BackButtonDispatcher backButtonDispatcher;
final BackButtonDispatcher? backButtonDispatcher;
/// {@macro flutter.widgets.widgetsApp.builder}
///
/// Material specific features such as [showDialog] and [showMenu], and widgets
/// such as [Tooltip], [PopupMenuButton], also require a [Navigator] to properly
/// function.
final TransitionBuilder builder;
final TransitionBuilder? builder;
/// {@macro flutter.widgets.widgetsApp.title}
///
......@@ -320,7 +318,7 @@ class MaterialApp extends StatefulWidget {
/// {@macro flutter.widgets.widgetsApp.onGenerateTitle}
///
/// This value is passed unmodified to [WidgetsApp.onGenerateTitle].
final GenerateAppTitle onGenerateTitle;
final GenerateAppTitle? onGenerateTitle;
/// Default visual properties, like colors fonts and shapes, for this app's
/// material widgets.
......@@ -339,7 +337,7 @@ class MaterialApp extends StatefulWidget {
/// and [darkTheme] in [MaterialApp].
/// * [ThemeData.brightness], which indicates the [Brightness] of a theme's
/// colors.
final ThemeData theme;
final ThemeData? theme;
/// The [ThemeData] to use when a 'dark mode' is requested by the system.
///
......@@ -361,7 +359,7 @@ class MaterialApp extends StatefulWidget {
/// and [darkTheme] in [MaterialApp].
/// * [ThemeData.brightness], which is typically set to the value of
/// [MediaQueryData.platformBrightness].
final ThemeData darkTheme;
final ThemeData? darkTheme;
/// The [ThemeData] to use when 'high contrast' is requested by the system.
///
......@@ -374,7 +372,7 @@ class MaterialApp extends StatefulWidget {
///
/// * [MediaQueryData.highContrast], which indicates the platform's
/// desire to increase contrast.
final ThemeData highContrastTheme;
final ThemeData? highContrastTheme;
/// The [ThemeData] to use when a 'dark mode' and 'high contrast' is requested
/// by the system.
......@@ -390,7 +388,7 @@ class MaterialApp extends StatefulWidget {
///
/// * [MediaQueryData.highContrast], which indicates the platform's
/// desire to increase contrast.
final ThemeData highContrastDarkTheme;
final ThemeData? highContrastDarkTheme;
/// Determines which theme will be used by the application if both [theme]
/// and [darkTheme] are provided.
......@@ -416,13 +414,13 @@ class MaterialApp extends StatefulWidget {
/// * [darkTheme], which is used when a dark mode is selected.
/// * [ThemeData.brightness], which indicates to various parts of the
/// system what kind of theme is being used.
final ThemeMode themeMode;
final ThemeMode? themeMode;
/// {@macro flutter.widgets.widgetsApp.color}
final Color color;
final Color? color;
/// {@macro flutter.widgets.widgetsApp.locale}
final Locale locale;
final Locale? locale;
/// {@macro flutter.widgets.widgetsApp.localizationsDelegates}
///
......@@ -515,17 +513,17 @@ class MaterialApp extends StatefulWidget {
/// which provides material localizations for many languages.
/// * The Flutter Internationalization Tutorial,
/// <https://flutter.dev/tutorials/internationalization/>.
final Iterable<LocalizationsDelegate<dynamic>> localizationsDelegates;
final Iterable<LocalizationsDelegate<dynamic>>? localizationsDelegates;
/// {@macro flutter.widgets.widgetsApp.localeListResolutionCallback}
///
/// This callback is passed along to the [WidgetsApp] built by this widget.
final LocaleListResolutionCallback localeListResolutionCallback;
final LocaleListResolutionCallback? localeListResolutionCallback;
/// {@macro flutter.widgets.widgetsApp.localeResolutionCallback}
///
/// This callback is passed along to the [WidgetsApp] built by this widget.
final LocaleResolutionCallback localeResolutionCallback;
final LocaleResolutionCallback? localeResolutionCallback;
/// {@macro flutter.widgets.widgetsApp.supportedLocales}
///
......@@ -587,7 +585,7 @@ class MaterialApp extends StatefulWidget {
/// ```
/// {@end-tool}
/// {@macro flutter.widgets.widgetsApp.shortcuts.seeAlso}
final Map<LogicalKeySet, Intent> shortcuts;
final Map<LogicalKeySet, Intent>? shortcuts;
/// {@macro flutter.widgets.widgetsApp.actions}
/// {@tool snippet}
......@@ -620,10 +618,10 @@ class MaterialApp extends StatefulWidget {
/// ```
/// {@end-tool}
/// {@macro flutter.widgets.widgetsApp.actions.seeAlso}
final Map<Type, Action<Intent>> actions;
final Map<Type, Action<Intent>>? actions;
/// {@macro flutter.widgets.widgetsApp.restorationScopeId}
final String restorationScopeId;
final String? restorationScopeId;
/// Turns on a [GridPaper] overlay that paints a baseline grid
/// Material apps.
......@@ -643,7 +641,7 @@ class MaterialApp extends StatefulWidget {
/// Used by the [MaterialApp].
static HeroController createMaterialHeroController() {
return HeroController(
createRectTween: (Rect begin, Rect end) {
createRectTween: (Rect? begin, Rect? end) {
return MaterialRectArcTween(begin: begin, end: end);
},
);
......@@ -653,7 +651,7 @@ class MaterialApp extends StatefulWidget {
class _MaterialScrollBehavior extends ScrollBehavior {
@override
TargetPlatform getPlatform(BuildContext context) {
return Theme.of(context).platform;
return Theme.of(context)!.platform;
}
@override
......@@ -671,15 +669,14 @@ class _MaterialScrollBehavior extends ScrollBehavior {
return GlowingOverscrollIndicator(
child: child,
axisDirection: axisDirection,
color: Theme.of(context).accentColor,
color: Theme.of(context)!.accentColor,
);
}
return null;
}
}
class _MaterialAppState extends State<MaterialApp> {
HeroController _heroController;
late HeroController _heroController;
bool get _usesRouter => widget.routerDelegate != null;
......@@ -696,7 +693,7 @@ class _MaterialAppState extends State<MaterialApp> {
// _MaterialLocalizationsDelegate.
Iterable<LocalizationsDelegate<dynamic>> get _localizationsDelegates sync* {
if (widget.localizationsDelegates != null)
yield* widget.localizationsDelegates;
yield* widget.localizationsDelegates!;
yield DefaultMaterialLocalizations.delegate;
yield DefaultCupertinoLocalizations.delegate;
}
......@@ -709,14 +706,14 @@ class _MaterialAppState extends State<MaterialApp> {
);
}
Widget _materialBuilder(BuildContext context, Widget child) {
Widget _materialBuilder(BuildContext context, Widget? child) {
// Resolve which theme to use based on brightness and high contrast.
final ThemeMode mode = widget.themeMode ?? ThemeMode.system;
final Brightness platformBrightness = MediaQuery.platformBrightnessOf(context);
final bool useDarkTheme = mode == ThemeMode.dark
|| (mode == ThemeMode.system && platformBrightness == ui.Brightness.dark);
final bool highContrast = MediaQuery.highContrastOf(context);
ThemeData theme;
ThemeData? theme;
if (useDarkTheme && highContrast && widget.highContrastDarkTheme != null) {
theme = widget.highContrastDarkTheme;
......@@ -744,10 +741,10 @@ class _MaterialAppState extends State<MaterialApp> {
// 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);
return widget.builder!(context, child);
},
)
: child,
: child!,
);
}
......@@ -764,8 +761,8 @@ class _MaterialAppState extends State<MaterialApp> {
return WidgetsApp.router(
key: GlobalObjectKey(this),
routeInformationProvider: widget.routeInformationProvider,
routeInformationParser: widget.routeInformationParser,
routerDelegate: widget.routerDelegate,
routeInformationParser: widget.routeInformationParser!,
routerDelegate: widget.routerDelegate!,
backButtonDispatcher: widget.backButtonDispatcher,
builder: _materialBuilder,
title: widget.title,
......@@ -792,12 +789,12 @@ class _MaterialAppState extends State<MaterialApp> {
return WidgetsApp(
key: GlobalObjectKey(this),
navigatorKey: widget.navigatorKey,
navigatorObservers: widget.navigatorObservers,
navigatorObservers: widget.navigatorObservers!,
pageRouteBuilder: <T>(RouteSettings settings, WidgetBuilder builder) {
return MaterialPageRoute<T>(settings: settings, builder: builder);
},
home: widget.home,
routes: widget.routes,
routes: widget.routes!,
initialRoute: widget.initialRoute,
onGenerateRoute: widget.onGenerateRoute,
onGenerateInitialRoutes: widget.onGenerateInitialRoutes,
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:math' as math;
import 'package:flutter/foundation.dart';
......@@ -192,7 +190,7 @@ class AppBar extends StatefulWidget implements PreferredSizeWidget {
///
/// Typically used in the [Scaffold.appBar] property.
AppBar({
Key key,
Key? key,
this.leading,
this.automaticallyImplyLeading = true,
this.title,
......@@ -221,7 +219,7 @@ class AppBar extends StatefulWidget implements PreferredSizeWidget {
assert(titleSpacing != null),
assert(toolbarOpacity != null),
assert(bottomOpacity != null),
preferredSize = Size.fromHeight(toolbarHeight ?? kToolbarHeight + (bottom?.preferredSize?.height ?? 0.0)),
preferredSize = Size.fromHeight(toolbarHeight ?? kToolbarHeight + (bottom?.preferredSize.height ?? 0.0)),
super(key: key);
/// A widget to display before the [title].
......@@ -269,7 +267,7 @@ class AppBar extends StatefulWidget implements PreferredSizeWidget {
///
/// * [Scaffold.appBar], in which an [AppBar] is usually placed.
/// * [Scaffold.drawer], in which the [Drawer] is usually placed.
final Widget leading;
final Widget? leading;
/// Controls whether we should try to imply the leading widget if null.
///
......@@ -308,7 +306,7 @@ class AppBar extends StatefulWidget implements PreferredSizeWidget {
/// ),
/// )
/// ```
final Widget title;
final Widget? title;
/// Widgets to display in a row after the [title] widget.
///
......@@ -319,7 +317,7 @@ class AppBar extends StatefulWidget implements PreferredSizeWidget {
/// The [actions] become the trailing component of the [NavigationToolbar] built
/// by this widget. The height of each action is constrained to be no bigger
/// than the [toolbarHeight].
final List<Widget> actions;
final List<Widget>? actions;
/// This widget is stacked behind the toolbar and the tab bar. It's height will
/// be the same as the app bar's overall height.
......@@ -329,7 +327,7 @@ class AppBar extends StatefulWidget implements PreferredSizeWidget {
/// changes the [AppBar]'s height when scrolled.
///
/// Typically a [FlexibleSpaceBar]. See [FlexibleSpaceBar] for details.
final Widget flexibleSpace;
final Widget? flexibleSpace;
/// This widget appears across the bottom of the app bar.
///
......@@ -339,7 +337,7 @@ class AppBar extends StatefulWidget implements PreferredSizeWidget {
/// See also:
///
/// * [PreferredSize], which can be used to give an arbitrary widget a preferred size.
final PreferredSizeWidget bottom;
final PreferredSizeWidget? bottom;
/// The z-coordinate at which to place this app bar relative to its parent.
///
......@@ -350,20 +348,20 @@ class AppBar extends StatefulWidget implements PreferredSizeWidget {
/// If this property is null, then [AppBarTheme.elevation] of
/// [ThemeData.appBarTheme] is used. If that is also null, the default value
/// is 4.
final double elevation;
final double? elevation;
/// The color to paint the shadow below the app bar.
///
/// If this property is null, then [AppBarTheme.shadowColor] of
/// [ThemeData.appBarTheme] is used. If that is also null, the default value
/// is fully opaque black.
final Color shadowColor;
final Color? shadowColor;
/// The material's shape as well its shadow.
///
/// A shadow is only displayed if the [elevation] is greater than
/// zero.
final ShapeBorder shape;
final ShapeBorder? shape;
/// The color to use for the app bar's material. Typically this should be set
/// along with [brightness], [iconTheme], [textTheme].
......@@ -371,7 +369,7 @@ class AppBar extends StatefulWidget implements PreferredSizeWidget {
/// If this property is null, then [AppBarTheme.color] of
/// [ThemeData.appBarTheme] is used. If that is also null, then
/// [ThemeData.primaryColor] is used.
final Color backgroundColor;
final Color? backgroundColor;
/// The brightness of the app bar's material. Typically this is set along
/// with [backgroundColor], [iconTheme], [textTheme].
......@@ -379,7 +377,7 @@ class AppBar extends StatefulWidget implements PreferredSizeWidget {
/// If this property is null, then [AppBarTheme.brightness] of
/// [ThemeData.appBarTheme] is used. If that is also null, then
/// [ThemeData.primaryColorBrightness] is used.
final Brightness brightness;
final Brightness? brightness;
/// The color, opacity, and size to use for app bar icons. Typically this
/// is set along with [backgroundColor], [brightness], [textTheme].
......@@ -387,7 +385,7 @@ class AppBar extends StatefulWidget implements PreferredSizeWidget {
/// If this property is null, then [AppBarTheme.iconTheme] of
/// [ThemeData.appBarTheme] is used. If that is also null, then
/// [ThemeData.primaryIconTheme] is used.
final IconThemeData iconTheme;
final IconThemeData? iconTheme;
/// The color, opacity, and size to use for the icons that appear in the app
/// bar's [actions]. This should only be used when the [actions] should be
......@@ -397,7 +395,7 @@ class AppBar extends StatefulWidget implements PreferredSizeWidget {
/// If this property is null, then [AppBarTheme.actionsIconTheme] of
/// [ThemeData.appBarTheme] is used. If that is also null, then this falls
/// back to [iconTheme].
final IconThemeData actionsIconTheme;
final IconThemeData? actionsIconTheme;
/// The typographic styles to use for text in the app bar. Typically this is
/// set along with [brightness] [backgroundColor], [iconTheme].
......@@ -405,7 +403,7 @@ class AppBar extends StatefulWidget implements PreferredSizeWidget {
/// If this property is null, then [AppBarTheme.textTheme] of
/// [ThemeData.appBarTheme] is used. If that is also null, then
/// [ThemeData.primaryTextTheme] is used.
final TextTheme textTheme;
final TextTheme? textTheme;
/// Whether this app bar is being displayed at the top of the screen.
///
......@@ -419,7 +417,7 @@ class AppBar extends StatefulWidget implements PreferredSizeWidget {
/// If this property is null, then [AppBarTheme.centerTitle] of
/// [ThemeData.appBarTheme] is used. If that is also null, then value is
/// adapted to the current [TargetPlatform].
final bool centerTitle;
final bool? centerTitle;
/// Whether the title should be wrapped with header [Semantics].
///
......@@ -461,18 +459,18 @@ class AppBar extends StatefulWidget implements PreferredSizeWidget {
/// Defines the height of the toolbar component of an [AppBar].
///
/// By default, the value of `toolbarHeight` is [kToolbarHeight].
final double toolbarHeight;
final double? toolbarHeight;
/// Defines the width of [leading] widget.
///
/// By default, the value of `leadingWidth` is 56.0.
final double leadingWidth;
final double? leadingWidth;
bool _getEffectiveCenterTitle(ThemeData theme) {
if (centerTitle != null)
return centerTitle;
return centerTitle!;
if (theme.appBarTheme.centerTitle != null)
return theme.appBarTheme.centerTitle;
return theme.appBarTheme.centerTitle!;
assert(theme.platform != null);
switch (theme.platform) {
case TargetPlatform.android:
......@@ -482,9 +480,8 @@ class AppBar extends StatefulWidget implements PreferredSizeWidget {
return false;
case TargetPlatform.iOS:
case TargetPlatform.macOS:
return actions == null || actions.length < 2;
return actions == null || actions!.length < 2;
}
return null;
}
@override
......@@ -496,21 +493,21 @@ class _AppBarState extends State<AppBar> {
static const Color _defaultShadowColor = Color(0xFF000000);
void _handleDrawerButton() {
Scaffold.of(context).openDrawer();
Scaffold.of(context)!.openDrawer();
}
void _handleDrawerButtonEnd() {
Scaffold.of(context).openEndDrawer();
Scaffold.of(context)!.openEndDrawer();
}
@override
Widget build(BuildContext context) {
assert(!widget.primary || debugCheckHasMediaQuery(context));
assert(debugCheckHasMaterialLocalizations(context));
final ThemeData theme = Theme.of(context);
final ThemeData? theme = Theme.of(context);
final AppBarTheme appBarTheme = AppBarTheme.of(context);
final ScaffoldState scaffold = Scaffold.of(context, nullOk: true);
final ModalRoute<dynamic> parentRoute = ModalRoute.of(context);
final ScaffoldState? scaffold = Scaffold.of(context, nullOk: true);
final ModalRoute<dynamic>? parentRoute = ModalRoute.of(context);
final bool hasDrawer = scaffold?.hasDrawer ?? false;
final bool hasEndDrawer = scaffold?.hasEndDrawer ?? false;
......@@ -521,23 +518,23 @@ class _AppBarState extends State<AppBar> {
IconThemeData overallIconTheme = widget.iconTheme
?? appBarTheme.iconTheme
?? theme.primaryIconTheme;
?? theme!.primaryIconTheme;
IconThemeData actionsIconTheme = widget.actionsIconTheme
?? appBarTheme.actionsIconTheme
?? overallIconTheme;
TextStyle centerStyle = widget.textTheme?.headline6
TextStyle? centerStyle = widget.textTheme?.headline6
?? appBarTheme.textTheme?.headline6
?? theme.primaryTextTheme.headline6;
TextStyle sideStyle = widget.textTheme?.bodyText2
?? theme!.primaryTextTheme.headline6;
TextStyle? sideStyle = widget.textTheme?.bodyText2
?? appBarTheme.textTheme?.bodyText2
?? theme.primaryTextTheme.bodyText2;
?? theme!.primaryTextTheme.bodyText2;
if (widget.toolbarOpacity != 1.0) {
final double opacity = const Interval(0.25, 1.0, curve: Curves.fastOutSlowIn).transform(widget.toolbarOpacity);
if (centerStyle?.color != null)
centerStyle = centerStyle.copyWith(color: centerStyle.color.withOpacity(opacity));
centerStyle = centerStyle!.copyWith(color: centerStyle.color!.withOpacity(opacity));
if (sideStyle?.color != null)
sideStyle = sideStyle.copyWith(color: sideStyle.color.withOpacity(opacity));
sideStyle = sideStyle!.copyWith(color: sideStyle.color!.withOpacity(opacity));
overallIconTheme = overallIconTheme.copyWith(
opacity: opacity * (overallIconTheme.opacity ?? 1.0)
);
......@@ -546,13 +543,13 @@ class _AppBarState extends State<AppBar> {
);
}
Widget leading = widget.leading;
Widget? leading = widget.leading;
if (leading == null && widget.automaticallyImplyLeading) {
if (hasDrawer) {
leading = IconButton(
icon: const Icon(Icons.menu),
onPressed: _handleDrawerButton,
tooltip: MaterialLocalizations.of(context).openAppDrawerTooltip,
tooltip: MaterialLocalizations.of(context)!.openAppDrawerTooltip,
);
} else {
if (!hasEndDrawer && canPop)
......@@ -566,10 +563,10 @@ class _AppBarState extends State<AppBar> {
);
}
Widget title = widget.title;
Widget? title = widget.title;
if (title != null) {
bool namesRoute;
switch (theme.platform) {
bool? namesRoute;
switch (theme!.platform) {
case TargetPlatform.android:
case TargetPlatform.fuchsia:
case TargetPlatform.linux:
......@@ -602,7 +599,7 @@ class _AppBarState extends State<AppBar> {
// sizes. To opt out, wrap the [title] widget in a [MediaQuery] widget
// with [MediaQueryData.textScaleFactor] set to
// `MediaQuery.textScaleFactorOf(context)`.
final MediaQueryData mediaQueryData = MediaQuery.of(context);
final MediaQueryData mediaQueryData = MediaQuery.of(context)!;
title = MediaQuery(
data: mediaQueryData.copyWith(
textScaleFactor: math.min(
......@@ -614,18 +611,18 @@ class _AppBarState extends State<AppBar> {
);
}
Widget actions;
if (widget.actions != null && widget.actions.isNotEmpty) {
Widget? actions;
if (widget.actions != null && widget.actions!.isNotEmpty) {
actions = Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: widget.actions,
children: widget.actions!,
);
} else if (hasEndDrawer) {
actions = IconButton(
icon: const Icon(Icons.menu),
onPressed: _handleDrawerButtonEnd,
tooltip: MaterialLocalizations.of(context).openAppDrawerTooltip,
tooltip: MaterialLocalizations.of(context)!.openAppDrawerTooltip,
);
}
......@@ -641,7 +638,7 @@ class _AppBarState extends State<AppBar> {
leading: leading,
middle: title,
trailing: actions,
centerMiddle: widget._getEffectiveCenterTitle(theme),
centerMiddle: widget._getEffectiveCenterTitle(theme!),
middleSpacing: widget.titleSpacing,
);
......@@ -670,7 +667,7 @@ class _AppBarState extends State<AppBar> {
),
),
if (widget.bottomOpacity == 1.0)
widget.bottom
widget.bottom!
else
Opacity(
opacity: const Interval(0.25, 1.0, curve: Curves.fastOutSlowIn).transform(widget.bottomOpacity),
......@@ -749,7 +746,7 @@ class _AppBarState extends State<AppBar> {
}
class _FloatingAppBar extends StatefulWidget {
const _FloatingAppBar({ Key key, this.child }) : super(key: key);
const _FloatingAppBar({ Key? key, required this.child }) : super(key: key);
final Widget child;
......@@ -760,26 +757,26 @@ class _FloatingAppBar extends StatefulWidget {
// A wrapper for the widget created by _SliverAppBarDelegate that starts and
// stops the floating app bar's snap-into-view or snap-out-of-view animation.
class _FloatingAppBarState extends State<_FloatingAppBar> {
ScrollPosition _position;
ScrollPosition? _position;
@override
void didChangeDependencies() {
super.didChangeDependencies();
if (_position != null)
_position.isScrollingNotifier.removeListener(_isScrollingListener);
_position!.isScrollingNotifier.removeListener(_isScrollingListener);
_position = Scrollable.of(context)?.position;
if (_position != null)
_position.isScrollingNotifier.addListener(_isScrollingListener);
_position!.isScrollingNotifier.addListener(_isScrollingListener);
}
@override
void dispose() {
if (_position != null)
_position.isScrollingNotifier.removeListener(_isScrollingListener);
_position!.isScrollingNotifier.removeListener(_isScrollingListener);
super.dispose();
}
RenderSliverFloatingPersistentHeader _headerRenderer() {
RenderSliverFloatingPersistentHeader? _headerRenderer() {
return context.findAncestorRenderObjectOfType<RenderSliverFloatingPersistentHeader>();
}
......@@ -789,11 +786,11 @@ class _FloatingAppBarState extends State<_FloatingAppBar> {
// When a scroll stops, then maybe snap the appbar into view.
// Similarly, when a scroll starts, then maybe stop the snap animation.
final RenderSliverFloatingPersistentHeader header = _headerRenderer();
if (_position.isScrollingNotifier.value)
header?.maybeStopSnapAnimation(_position.userScrollDirection);
final RenderSliverFloatingPersistentHeader? header = _headerRenderer();
if (_position!.isScrollingNotifier.value)
header?.maybeStopSnapAnimation(_position!.userScrollDirection);
else
header?.maybeStartSnapAnimation(_position.userScrollDirection);
header?.maybeStartSnapAnimation(_position!.userScrollDirection);
}
@override
......@@ -802,69 +799,69 @@ class _FloatingAppBarState extends State<_FloatingAppBar> {
class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
_SliverAppBarDelegate({
@required this.leading,
@required this.automaticallyImplyLeading,
@required this.title,
@required this.actions,
@required this.flexibleSpace,
@required this.bottom,
@required this.elevation,
@required this.shadowColor,
@required this.forceElevated,
@required this.backgroundColor,
@required this.brightness,
@required this.iconTheme,
@required this.actionsIconTheme,
@required this.textTheme,
@required this.primary,
@required this.centerTitle,
@required this.excludeHeaderSemantics,
@required this.titleSpacing,
@required this.expandedHeight,
@required this.collapsedHeight,
@required this.topPadding,
@required this.floating,
@required this.pinned,
@required this.vsync,
@required this.snapConfiguration,
@required this.stretchConfiguration,
@required this.showOnScreenConfiguration,
@required this.shape,
@required this.toolbarHeight,
@required this.leadingWidth,
required this.leading,
required this.automaticallyImplyLeading,
required this.title,
required this.actions,
required this.flexibleSpace,
required this.bottom,
required this.elevation,
required this.shadowColor,
required this.forceElevated,
required this.backgroundColor,
required this.brightness,
required this.iconTheme,
required this.actionsIconTheme,
required this.textTheme,
required this.primary,
required this.centerTitle,
required this.excludeHeaderSemantics,
required this.titleSpacing,
required this.expandedHeight,
required this.collapsedHeight,
required this.topPadding,
required this.floating,
required this.pinned,
required this.vsync,
required this.snapConfiguration,
required this.stretchConfiguration,
required this.showOnScreenConfiguration,
required this.shape,
required this.toolbarHeight,
required this.leadingWidth,
}) : assert(primary || topPadding == 0.0),
assert(
!floating || (snapConfiguration == null && showOnScreenConfiguration == null) || vsync != null,
'vsync cannot be null when snapConfiguration or showOnScreenConfiguration is not null, and floating is true',
),
_bottomHeight = bottom?.preferredSize?.height ?? 0.0;
_bottomHeight = bottom?.preferredSize.height ?? 0.0;
final Widget leading;
final Widget? leading;
final bool automaticallyImplyLeading;
final Widget title;
final List<Widget> actions;
final Widget flexibleSpace;
final PreferredSizeWidget bottom;
final double elevation;
final Color shadowColor;
final Widget? title;
final List<Widget>? actions;
final Widget? flexibleSpace;
final PreferredSizeWidget? bottom;
final double? elevation;
final Color? shadowColor;
final bool forceElevated;
final Color backgroundColor;
final Brightness brightness;
final IconThemeData iconTheme;
final IconThemeData actionsIconTheme;
final TextTheme textTheme;
final Color? backgroundColor;
final Brightness? brightness;
final IconThemeData? iconTheme;
final IconThemeData? actionsIconTheme;
final TextTheme? textTheme;
final bool primary;
final bool centerTitle;
final bool? centerTitle;
final bool excludeHeaderSemantics;
final double titleSpacing;
final double expandedHeight;
final double? expandedHeight;
final double collapsedHeight;
final double topPadding;
final bool floating;
final bool pinned;
final ShapeBorder shape;
final double toolbarHeight;
final double leadingWidth;
final ShapeBorder? shape;
final double? toolbarHeight;
final double? leadingWidth;
final double _bottomHeight;
......@@ -878,13 +875,13 @@ class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
final TickerProvider vsync;
@override
final FloatingHeaderSnapConfiguration snapConfiguration;
final FloatingHeaderSnapConfiguration? snapConfiguration;
@override
final OverScrollHeaderStretchConfiguration stretchConfiguration;
final OverScrollHeaderStretchConfiguration? stretchConfiguration;
@override
final PersistentHeaderShowOnScreenConfiguration showOnScreenConfiguration;
final PersistentHeaderShowOnScreenConfiguration? showOnScreenConfiguration;
@override
Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) {
......@@ -894,7 +891,7 @@ class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
final bool isPinnedWithOpacityFade = pinned && floating && bottom != null && extraToolbarHeight == 0.0;
final double toolbarOpacity = !pinned || isPinnedWithOpacityFade
? (visibleToolbarHeight / (toolbarHeight ?? kToolbarHeight)).clamp(0.0, 1.0) as double
? (visibleToolbarHeight / (toolbarHeight ?? kToolbarHeight)).clamp(0.0, 1.0)
: 1.0;
final Widget appBar = FlexibleSpaceBar.createSettings(
......@@ -924,7 +921,7 @@ class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
titleSpacing: titleSpacing,
shape: shape,
toolbarOpacity: toolbarOpacity,
bottomOpacity: pinned ? 1.0 : ((visibleMainHeight / _bottomHeight).clamp(0.0, 1.0) as double),
bottomOpacity: pinned ? 1.0 : ((visibleMainHeight / _bottomHeight).clamp(0.0, 1.0)),
toolbarHeight: toolbarHeight,
leadingWidth: leadingWidth,
),
......@@ -1054,7 +1051,7 @@ class SliverAppBar extends StatefulWidget {
/// The arguments [forceElevated], [primary], [floating], [pinned], [snap]
/// and [automaticallyImplyLeading] must not be null.
const SliverAppBar({
Key key,
Key? key,
this.leading,
this.automaticallyImplyLeading = true,
this.title,
......@@ -1106,7 +1103,7 @@ class SliverAppBar extends StatefulWidget {
/// [IconButton] that opens the drawer. If there's no [Drawer] and the parent
/// [Navigator] can go back, the [AppBar] will use a [BackButton] that calls
/// [Navigator.maybePop].
final Widget leading;
final Widget? leading;
/// Controls whether we should try to imply the leading widget if null.
///
......@@ -1119,7 +1116,7 @@ class SliverAppBar extends StatefulWidget {
///
/// Typically a [Text] widget containing a description of the current contents
/// of the app.
final Widget title;
final Widget? title;
/// Widgets to display after the [title] widget.
///
......@@ -1152,7 +1149,7 @@ class SliverAppBar extends StatefulWidget {
/// )
/// ```
/// {@end-tool}
final List<Widget> actions;
final List<Widget>? actions;
/// This widget is stacked behind the toolbar and the tab bar. It's height will
/// be the same as the app bar's overall height.
......@@ -1161,7 +1158,7 @@ class SliverAppBar extends StatefulWidget {
/// must be large enough to accommodate the [SliverAppBar.flexibleSpace] widget.
///
/// Typically a [FlexibleSpaceBar]. See [FlexibleSpaceBar] for details.
final Widget flexibleSpace;
final Widget? flexibleSpace;
/// This widget appears across the bottom of the app bar.
///
......@@ -1171,7 +1168,7 @@ class SliverAppBar extends StatefulWidget {
/// See also:
///
/// * [PreferredSize], which can be used to give an arbitrary widget a preferred size.
final PreferredSizeWidget bottom;
final PreferredSizeWidget? bottom;
/// The z-coordinate at which to place this app bar when it is above other
/// content. This controls the size of the shadow below the app bar.
......@@ -1184,7 +1181,7 @@ class SliverAppBar extends StatefulWidget {
/// no content underneath it. For example, if the app bar is [pinned] but no
/// content is scrolled under it, or if it scrolls with the content, then no
/// shadow is drawn, regardless of the value of [elevation].
final double elevation;
final double? elevation;
/// The color to paint the shadow below the app bar. Typically this should be set
/// along with [elevation].
......@@ -1192,7 +1189,7 @@ class SliverAppBar extends StatefulWidget {
/// If this property is null, then [AppBarTheme.shadowColor] of
/// [ThemeData.appBarTheme] is used, if that is also null, the default value
/// is fully opaque black.
final Color shadowColor;
final Color? shadowColor;
/// Whether to show the shadow appropriate for the [elevation] even if the
/// content is not scrolled under the [AppBar].
......@@ -1211,7 +1208,7 @@ class SliverAppBar extends StatefulWidget {
/// If this property is null, then [AppBarTheme.color] of
/// [ThemeData.appBarTheme] is used. If that is also null, then
/// [ThemeData.primaryColor] is used.
final Color backgroundColor;
final Color? backgroundColor;
/// The brightness of the app bar's material. Typically this is set along
/// with [backgroundColor], [iconTheme], [textTheme].
......@@ -1219,7 +1216,7 @@ class SliverAppBar extends StatefulWidget {
/// If this property is null, then [AppBarTheme.brightness] of
/// [ThemeData.appBarTheme] is used. If that is also null, then
/// [ThemeData.primaryColorBrightness] is used.
final Brightness brightness;
final Brightness? brightness;
/// The color, opacity, and size to use for app bar icons. Typically this
/// is set along with [backgroundColor], [brightness], [textTheme].
......@@ -1227,7 +1224,7 @@ class SliverAppBar extends StatefulWidget {
/// If this property is null, then [AppBarTheme.iconTheme] of
/// [ThemeData.appBarTheme] is used, if that is also null, then
/// [ThemeData.primaryIconTheme] is used.
final IconThemeData iconTheme;
final IconThemeData? iconTheme;
/// The color, opacity, and size to use for trailing app bar icons. This
/// should only be used when the trailing icons should be themed differently
......@@ -1236,7 +1233,7 @@ class SliverAppBar extends StatefulWidget {
/// If this property is null, then [AppBarTheme.actionsIconTheme] of
/// [ThemeData.appBarTheme] is used, if that is also null, then this falls
/// back to [iconTheme].
final IconThemeData actionsIconTheme;
final IconThemeData? actionsIconTheme;
/// The typographic styles to use for text in the app bar. Typically this is
/// set along with [brightness] [backgroundColor], [iconTheme].
......@@ -1244,7 +1241,7 @@ class SliverAppBar extends StatefulWidget {
/// If this property is null, then [AppBarTheme.textTheme] of
/// [ThemeData.appBarTheme] is used, if that is also null, then
/// [ThemeData.primaryTextTheme] is used.
final TextTheme textTheme;
final TextTheme? textTheme;
/// Whether this app bar is being displayed at the top of the screen.
///
......@@ -1255,7 +1252,7 @@ class SliverAppBar extends StatefulWidget {
/// Whether the title should be centered.
///
/// Defaults to being adapted to the current [TargetPlatform].
final bool centerTitle;
final bool? centerTitle;
/// Whether the title should be wrapped with header [Semantics].
///
......@@ -1279,7 +1276,7 @@ class SliverAppBar extends StatefulWidget {
/// If [pinned] and [floating] are true, with [bottom] set, the default
/// collapsed height is only the height of [PreferredSizeWidget.preferredSize]
/// with the [MediaQuery] top padding.
final double collapsedHeight;
final double? collapsedHeight;
/// The size of the app bar when it is fully expanded.
///
......@@ -1289,7 +1286,7 @@ class SliverAppBar extends StatefulWidget {
///
/// This does not include the status bar height (which will be automatically
/// included if [primary] is true).
final double expandedHeight;
final double? expandedHeight;
/// Whether the app bar should become visible as soon as the user scrolls
/// towards the app bar.
......@@ -1341,7 +1338,7 @@ class SliverAppBar extends StatefulWidget {
/// The material's shape as well as its shadow.
///
/// A shadow is only displayed if the [elevation] is greater than zero.
final ShapeBorder shape;
final ShapeBorder? shape;
/// If [snap] and [floating] are true then the floating app bar will "snap"
/// into view.
......@@ -1388,7 +1385,7 @@ class SliverAppBar extends StatefulWidget {
/// The callback function to be executed when a user over-scrolls to the
/// offset specified by [stretchTriggerOffset].
final AsyncCallback onStretchTrigger;
final AsyncCallback? onStretchTrigger;
/// Defines the height of the toolbar component of an [AppBar].
///
......@@ -1398,7 +1395,7 @@ class SliverAppBar extends StatefulWidget {
/// Defines the width of [leading] widget.
///
/// By default, the value of `leadingWidth` is 56.0.
final double leadingWidth;
final double? leadingWidth;
@override
_SliverAppBarState createState() => _SliverAppBarState();
......@@ -1407,9 +1404,9 @@ class SliverAppBar extends StatefulWidget {
// This class is only Stateful because it owns the TickerProvider used
// by the floating appbar snap animation (via FloatingHeaderSnapConfiguration).
class _SliverAppBarState extends State<SliverAppBar> with TickerProviderStateMixin {
FloatingHeaderSnapConfiguration _snapConfiguration;
OverScrollHeaderStretchConfiguration _stretchConfiguration;
PersistentHeaderShowOnScreenConfiguration _showOnScreenConfiguration;
FloatingHeaderSnapConfiguration? _snapConfiguration;
OverScrollHeaderStretchConfiguration? _stretchConfiguration;
PersistentHeaderShowOnScreenConfiguration? _showOnScreenConfiguration;
void _updateSnapConfiguration() {
if (widget.snap && widget.floating) {
......@@ -1456,8 +1453,8 @@ class _SliverAppBarState extends State<SliverAppBar> with TickerProviderStateMix
@override
Widget build(BuildContext context) {
assert(!widget.primary || debugCheckHasMediaQuery(context));
final double bottomHeight = widget.bottom?.preferredSize?.height ?? 0.0;
final double topPadding = widget.primary ? MediaQuery.of(context).padding.top : 0.0;
final double bottomHeight = widget.bottom?.preferredSize.height ?? 0.0;
final double topPadding = widget.primary ? MediaQuery.of(context)!.padding.top : 0.0;
final double collapsedHeight = (widget.pinned && widget.floating && widget.bottom != null)
? (widget.collapsedHeight ?? 0.0) + bottomHeight + topPadding
: (widget.collapsedHeight ?? widget.toolbarHeight) + bottomHeight + topPadding;
......@@ -1509,7 +1506,7 @@ class _SliverAppBarState extends State<SliverAppBar> with TickerProviderStateMix
// center it within its (NavigationToolbar) parent, and allow the
// parent to constrain the title's actual height.
class _AppBarTitleBox extends SingleChildRenderObjectWidget {
const _AppBarTitleBox({ Key key, @required Widget child }) : assert(child != null), super(key: key, child: child);
const _AppBarTitleBox({ Key? key, required Widget child }) : assert(child != null), super(key: key, child: child);
@override
_RenderAppBarTitleBox createRenderObject(BuildContext context) {
......@@ -1526,16 +1523,15 @@ class _AppBarTitleBox extends SingleChildRenderObjectWidget {
class _RenderAppBarTitleBox extends RenderAligningShiftedBox {
_RenderAppBarTitleBox({
RenderBox child,
TextDirection textDirection,
RenderBox? child,
TextDirection? textDirection,
}) : super(child: child, alignment: Alignment.center, textDirection: textDirection);
@override
void performLayout() {
final BoxConstraints constraints = this.constraints;
final BoxConstraints innerConstraints = constraints.copyWith(maxHeight: double.infinity);
child.layout(innerConstraints, parentUsesSize: true);
size = constraints.constrain(child.size);
child!.layout(innerConstraints, parentUsesSize: true);
size = constraints.constrain(child!.size);
alignChild();
}
}
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:ui' show lerpDouble;
import 'package:flutter/foundation.dart';
......@@ -46,54 +44,54 @@ class AppBarTheme with Diagnosticable {
/// Default value for [AppBar.brightness].
///
/// If null, [AppBar] uses [ThemeData.primaryColorBrightness].
final Brightness brightness;
final Brightness? brightness;
/// Default value for [AppBar.backgroundColor].
///
/// If null, [AppBar] uses [ThemeData.primaryColor].
final Color color;
final Color? color;
/// Default value for [AppBar.elevation].
///
/// If null, [AppBar] uses a default value of 4.0.
final double elevation;
final double? elevation;
/// Default value for [AppBar.shadowColor].
///
/// If null, [AppBar] uses a default value of fully opaque black.
final Color shadowColor;
final Color? shadowColor;
/// Default value for [AppBar.iconTheme].
///
/// If null, [AppBar] uses [ThemeData.primaryIconTheme].
final IconThemeData iconTheme;
final IconThemeData? iconTheme;
/// Default value for [AppBar.actionsIconTheme].
///
/// If null, [AppBar] uses [ThemeData.primaryIconTheme].
final IconThemeData actionsIconTheme;
final IconThemeData? actionsIconTheme;
/// Default value for [AppBar.textTheme].
///
/// If null, [AppBar] uses [ThemeData.primaryTextTheme].
final TextTheme textTheme;
final TextTheme? textTheme;
/// Default value for [AppBar.centerTitle].
///
/// If null, the value is adapted to current [TargetPlatform].
final bool centerTitle;
final bool? centerTitle;
/// Creates a copy of this object with the given fields replaced with the
/// new values.
AppBarTheme copyWith({
IconThemeData actionsIconTheme,
Brightness brightness,
Color color,
double elevation,
Color shadowColor,
IconThemeData iconTheme,
TextTheme textTheme,
bool centerTitle,
IconThemeData? actionsIconTheme,
Brightness? brightness,
Color? color,
double? elevation,
Color? shadowColor,
IconThemeData? iconTheme,
TextTheme? textTheme,
bool? centerTitle,
}) {
return AppBarTheme(
brightness: brightness ?? this.brightness,
......@@ -109,7 +107,7 @@ class AppBarTheme with Diagnosticable {
/// The [ThemeData.appBarTheme] property of the ambient [Theme].
static AppBarTheme of(BuildContext context) {
return Theme.of(context).appBarTheme;
return Theme.of(context)!.appBarTheme;
}
/// Linearly interpolate between two AppBar themes.
......@@ -117,7 +115,7 @@ class AppBarTheme with Diagnosticable {
/// The argument `t` must not be null.
///
/// {@macro dart.ui.shadow.lerp}
static AppBarTheme lerp(AppBarTheme a, AppBarTheme b, double t) {
static AppBarTheme lerp(AppBarTheme? a, AppBarTheme? b, double t) {
assert(t != null);
return AppBarTheme(
brightness: t < 0.5 ? a?.brightness : b?.brightness,
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'package:flutter/widgets.dart';
import 'debug.dart';
......@@ -27,7 +25,7 @@ import 'theme.dart';
class BackButtonIcon extends StatelessWidget {
/// Creates an icon that shows the appropriate "back" image for
/// the current platform (as obtained from the [Theme]).
const BackButtonIcon({ Key key }) : super(key: key);
const BackButtonIcon({ Key? key }) : super(key: key);
/// Returns the appropriate "back" icon for the given `platform`.
static IconData _getIconData(TargetPlatform platform) {
......@@ -41,12 +39,10 @@ class BackButtonIcon extends StatelessWidget {
case TargetPlatform.macOS:
return Icons.arrow_back_ios;
}
assert(false);
return null;
}
@override
Widget build(BuildContext context) => Icon(_getIconData(Theme.of(context).platform));
Widget build(BuildContext context) => Icon(_getIconData(Theme.of(context)!.platform));
}
/// A material design back button.
......@@ -78,13 +74,13 @@ class BackButtonIcon extends StatelessWidget {
class BackButton extends StatelessWidget {
/// Creates an [IconButton] with the appropriate "back" icon for the current
/// target platform.
const BackButton({ Key key, this.color, this.onPressed }) : super(key: key);
const BackButton({ Key? key, this.color, this.onPressed }) : super(key: key);
/// The color to use for the icon.
///
/// Defaults to the [IconThemeData.color] specified in the ambient [IconTheme],
/// which usually matches the ambient [Theme]'s [ThemeData.iconTheme].
final Color color;
final Color? color;
/// An override callback to perform instead of the default behavior which is
/// to pop the [Navigator].
......@@ -94,7 +90,7 @@ class BackButton extends StatelessWidget {
/// situations.
///
/// Defaults to null.
final VoidCallback onPressed;
final VoidCallback? onPressed;
@override
Widget build(BuildContext context) {
......@@ -102,10 +98,10 @@ class BackButton extends StatelessWidget {
return IconButton(
icon: const BackButtonIcon(),
color: color,
tooltip: MaterialLocalizations.of(context).backButtonTooltip,
tooltip: MaterialLocalizations.of(context)!.backButtonTooltip,
onPressed: () {
if (onPressed != null) {
onPressed();
onPressed!();
} else {
Navigator.maybePop(context);
}
......@@ -132,13 +128,13 @@ class BackButton extends StatelessWidget {
/// * [IconButton], to create other material design icon buttons.
class CloseButton extends StatelessWidget {
/// Creates a Material Design close button.
const CloseButton({ Key key, this.color, this.onPressed }) : super(key: key);
const CloseButton({ Key? key, this.color, this.onPressed }) : super(key: key);
/// The color to use for the icon.
///
/// Defaults to the [IconThemeData.color] specified in the ambient [IconTheme],
/// which usually matches the ambient [Theme]'s [ThemeData.iconTheme].
final Color color;
final Color? color;
/// An override callback to perform instead of the default behavior which is
/// to pop the [Navigator].
......@@ -148,7 +144,7 @@ class CloseButton extends StatelessWidget {
/// situations.
///
/// Defaults to null.
final VoidCallback onPressed;
final VoidCallback? onPressed;
@override
Widget build(BuildContext context) {
......@@ -156,10 +152,10 @@ class CloseButton extends StatelessWidget {
return IconButton(
icon: const Icon(Icons.close),
color: color,
tooltip: MaterialLocalizations.of(context).closeButtonTooltip,
tooltip: MaterialLocalizations.of(context)!.closeButtonTooltip,
onPressed: () {
if (onPressed != null) {
onPressed();
onPressed!();
} else {
Navigator.maybePop(context);
}
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'package:flutter/widgets.dart';
import 'banner_theme.dart';
......@@ -35,10 +33,10 @@ class MaterialBanner extends StatelessWidget {
/// The [actions], [content], and [forceActionsBelow] must be non-null.
/// The [actions.length] must be greater than 0.
const MaterialBanner({
Key key,
@required this.content,
Key? key,
required this.content,
this.contentTextStyle,
@required this.actions,
required this.actions,
this.leading,
this.backgroundColor,
this.padding,
......@@ -58,7 +56,7 @@ class MaterialBanner extends StatelessWidget {
///
/// If `null`, [MaterialBannerThemeData.contentTextStyle] is used. If that is
/// also `null`, [TextTheme.bodyText2] of [ThemeData.textTheme] is used.
final TextStyle contentTextStyle;
final TextStyle? contentTextStyle;
/// The set of actions that are displayed at the bottom or trailing side of
/// the [MaterialBanner].
......@@ -69,13 +67,13 @@ class MaterialBanner extends StatelessWidget {
/// The (optional) leading widget of the [MaterialBanner].
///
/// Typically an [Icon] widget.
final Widget leading;
final Widget? leading;
/// The color of the surface of this [MaterialBanner].
///
/// If `null`, [MaterialBannerThemeData.backgroundColor] is used. If that is
/// also `null`, [ColorScheme.surface] of [ThemeData.colorScheme] is used.
final Color backgroundColor;
final Color? backgroundColor;
/// The amount of space by which to inset the [content].
///
......@@ -84,12 +82,12 @@ class MaterialBanner extends StatelessWidget {
///
/// If the [actions] are trailing the [content], this defaults to
/// `EdgeInsetsDirectional.only(start: 16.0, top: 2.0)`.
final EdgeInsetsGeometry padding;
final EdgeInsetsGeometry? padding;
/// The amount of space by which to inset the [leading] widget.
///
/// This defaults to `EdgeInsetsDirectional.only(end: 16.0)`.
final EdgeInsetsGeometry leadingPadding;
final EdgeInsetsGeometry? leadingPadding;
/// An override to force the [actions] to be below the [content] regardless of
/// how many there are.
......@@ -104,7 +102,7 @@ class MaterialBanner extends StatelessWidget {
Widget build(BuildContext context) {
assert(actions.isNotEmpty);
final ThemeData theme = Theme.of(context);
final ThemeData? theme = Theme.of(context);
final MaterialBannerThemeData bannerTheme = MaterialBannerTheme.of(context);
final bool isSingleRow = actions.length == 1 && !forceActionsBelow;
......@@ -127,10 +125,10 @@ class MaterialBanner extends StatelessWidget {
final Color backgroundColor = this.backgroundColor
?? bannerTheme.backgroundColor
?? theme.colorScheme.surface;
final TextStyle textStyle = contentTextStyle
?? theme!.colorScheme.surface;
final TextStyle? textStyle = contentTextStyle
?? bannerTheme.contentTextStyle
?? theme.textTheme.bodyText2;
?? theme!.textTheme.bodyText2;
return Container(
color: backgroundColor,
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
......@@ -38,25 +36,25 @@ class MaterialBannerThemeData with Diagnosticable {
});
/// The background color of a [MaterialBanner].
final Color backgroundColor;
final Color? backgroundColor;
/// Used to configure the [DefaultTextStyle] for the [MaterialBanner.content]
/// widget.
final TextStyle contentTextStyle;
final TextStyle? contentTextStyle;
/// The amount of space by which to inset [MaterialBanner.content].
final EdgeInsetsGeometry padding;
final EdgeInsetsGeometry? padding;
/// The amount of space by which to inset [MaterialBanner.leading].
final EdgeInsetsGeometry leadingPadding;
final EdgeInsetsGeometry? leadingPadding;
/// Creates a copy of this object with the given fields replaced with the
/// new values.
MaterialBannerThemeData copyWith({
Color backgroundColor,
TextStyle contentTextStyle,
EdgeInsetsGeometry padding,
EdgeInsetsGeometry leadingPadding,
Color? backgroundColor,
TextStyle? contentTextStyle,
EdgeInsetsGeometry? padding,
EdgeInsetsGeometry? leadingPadding,
}) {
return MaterialBannerThemeData(
backgroundColor: backgroundColor ?? this.backgroundColor,
......@@ -71,7 +69,7 @@ class MaterialBannerThemeData with Diagnosticable {
/// The argument `t` must not be null.
///
/// {@macro dart.ui.shadow.lerp}
static MaterialBannerThemeData lerp(MaterialBannerThemeData a, MaterialBannerThemeData b, double t) {
static MaterialBannerThemeData lerp(MaterialBannerThemeData? a, MaterialBannerThemeData? b, double t) {
assert(t != null);
return MaterialBannerThemeData(
backgroundColor: Color.lerp(a?.backgroundColor, b?.backgroundColor, t),
......@@ -123,13 +121,13 @@ class MaterialBannerTheme extends InheritedTheme {
/// Creates a banner theme that controls the configurations for
/// [MaterialBanner]s in its widget subtree.
const MaterialBannerTheme({
Key key,
Key? key,
this.data,
Widget child,
required Widget child,
}) : super(key: key, child: child);
/// The properties for descendant [MaterialBanner] widgets.
final MaterialBannerThemeData data;
final MaterialBannerThemeData? data;
/// The closest instance of this class's [data] value that encloses the given
/// context.
......@@ -143,13 +141,13 @@ class MaterialBannerTheme extends InheritedTheme {
/// MaterialBannerThemeData theme = MaterialBannerTheme.of(context);
/// ```
static MaterialBannerThemeData of(BuildContext context) {
final MaterialBannerTheme bannerTheme = context.dependOnInheritedWidgetOfExactType<MaterialBannerTheme>();
return bannerTheme?.data ?? Theme.of(context).bannerTheme;
final MaterialBannerTheme? bannerTheme = context.dependOnInheritedWidgetOfExactType<MaterialBannerTheme>();
return bannerTheme?.data ?? Theme.of(context)!.bannerTheme;
}
@override
Widget wrap(BuildContext context, Widget child) {
final MaterialBannerTheme ancestorTheme = context.findAncestorWidgetOfExactType<MaterialBannerTheme>();
final MaterialBannerTheme? ancestorTheme = context.findAncestorWidgetOfExactType<MaterialBannerTheme>();
return identical(this, ancestorTheme) ? child : MaterialBannerTheme(data: data, child: child);
}
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'package:flutter/foundation.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';
......@@ -50,7 +48,7 @@ class BottomAppBar extends StatefulWidget {
/// If the corresponding [BottomAppBarTheme] property is null, then the default
/// specified in the property's documentation will be used.
const BottomAppBar({
Key key,
Key? key,
this.color,
this.elevation,
this.shape,
......@@ -68,14 +66,14 @@ class BottomAppBar extends StatefulWidget {
///
/// Typically this the child will be a [Row], with the first child
/// being an [IconButton] with the [Icons.menu] icon.
final Widget child;
final Widget? child;
/// The bottom app bar's background color.
///
/// If this property is null then [BottomAppBarTheme.color] of
/// [ThemeData.bottomAppBarTheme] is used. If that's null then
/// [ThemeData.bottomAppBarColor] is used.
final Color color;
final Color? color;
/// The z-coordinate at which to place this bottom app bar relative to its
/// parent.
......@@ -86,14 +84,14 @@ class BottomAppBar extends StatefulWidget {
/// If this property is null then [BottomAppBarTheme.elevation] of
/// [ThemeData.bottomAppBarTheme] is used. If that's null, the default value
/// is 8.
final double elevation;
final double? elevation;
/// The notch that is made for the floating action button.
///
/// If this property is null then [BottomAppBarTheme.shape] of
/// [ThemeData.bottomAppBarTheme] is used. If that's null then the shape will
/// be rectangular with no notch.
final NotchedShape shape;
final NotchedShape? shape;
/// {@macro flutter.widgets.Clip}
///
......@@ -111,19 +109,19 @@ class BottomAppBar extends StatefulWidget {
}
class _BottomAppBarState extends State<BottomAppBar> {
ValueListenable<ScaffoldGeometry> geometryListenable;
late ValueListenable<ScaffoldGeometry> geometryListenable;
static const double _defaultElevation = 8.0;
@override
void didChangeDependencies() {
super.didChangeDependencies();
geometryListenable = Scaffold.geometryOf(context);
geometryListenable = Scaffold.geometryOf(context)!;
}
@override
Widget build(BuildContext context) {
final BottomAppBarTheme babTheme = BottomAppBarTheme.of(context);
final NotchedShape notchedShape = widget.shape ?? babTheme.shape;
final NotchedShape? notchedShape = widget.shape ?? babTheme.shape;
final CustomClipper<Path> clipper = notchedShape != null
? _BottomAppBarClipper(
geometry: geometryListenable,
......@@ -132,7 +130,7 @@ class _BottomAppBarState extends State<BottomAppBar> {
)
: const ShapeBorderClipper(shape: RoundedRectangleBorder());
final double elevation = widget.elevation ?? babTheme.elevation ?? _defaultElevation;
final Color color = widget.color ?? babTheme.color ?? Theme.of(context).bottomAppBarColor;
final Color color = widget.color ?? babTheme.color ?? Theme.of(context)!.bottomAppBarColor;
final Color effectiveColor = ElevationOverlay.applyOverlay(context, color, elevation);
return PhysicalShape(
clipper: clipper,
......@@ -143,7 +141,7 @@ class _BottomAppBarState extends State<BottomAppBar> {
type: MaterialType.transparency,
child: widget.child == null
? null
: SafeArea(child: widget.child),
: SafeArea(child: widget.child!),
),
);
}
......@@ -151,9 +149,9 @@ class _BottomAppBarState extends State<BottomAppBar> {
class _BottomAppBarClipper extends CustomClipper<Path> {
const _BottomAppBarClipper({
@required this.geometry,
@required this.shape,
@required this.notchMargin,
required this.geometry,
required this.shape,
required this.notchMargin,
}) : assert(geometry != null),
assert(shape != null),
assert(notchMargin != null),
......@@ -168,9 +166,9 @@ class _BottomAppBarClipper extends CustomClipper<Path> {
// button is the floating action button's bounding rectangle in the
// coordinate system whose origin is at the appBar's top left corner,
// or null if there is no floating action button.
final Rect button = geometry.value.floatingActionButtonArea?.translate(
final Rect? button = geometry.value.floatingActionButtonArea?.translate(
0.0,
geometry.value.bottomNavigationBarTop * -1.0,
geometry.value.bottomNavigationBarTop! * -1.0,
);
return shape.getOuterPath(Offset.zero & size, button?.inflate(notchMargin));
}
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:ui' show lerpDouble;
import 'package:flutter/foundation.dart';
......@@ -39,20 +37,20 @@ class BottomAppBarTheme with Diagnosticable {
/// Default value for [BottomAppBar.color].
///
/// If null, [BottomAppBar] uses [ThemeData.bottomAppBarColor].
final Color color;
final Color? color;
/// Default value for [BottomAppBar.elevation].
final double elevation;
final double? elevation;
/// Default value for [BottomAppBar.shape].
final NotchedShape shape;
final NotchedShape? shape;
/// Creates a copy of this object but with the given fields replaced with the
/// new values.
BottomAppBarTheme copyWith({
Color color,
double elevation,
NotchedShape shape,
Color? color,
double? elevation,
NotchedShape? shape,
}) {
return BottomAppBarTheme(
color: color ?? this.color,
......@@ -63,7 +61,7 @@ class BottomAppBarTheme with Diagnosticable {
/// The [ThemeData.bottomAppBarTheme] property of the ambient [Theme].
static BottomAppBarTheme of(BuildContext context) {
return Theme.of(context).bottomAppBarTheme;
return Theme.of(context)!.bottomAppBarTheme;
}
/// Linearly interpolate between two BAB themes.
......@@ -71,7 +69,7 @@ class BottomAppBarTheme with Diagnosticable {
/// The argument `t` must not be null.
///
/// {@macro dart.ui.shadow.lerp}
static BottomAppBarTheme lerp(BottomAppBarTheme a, BottomAppBarTheme b, double t) {
static BottomAppBarTheme lerp(BottomAppBarTheme? a, BottomAppBarTheme? b, double t) {
assert(t != null);
return BottomAppBarTheme(
color: Color.lerp(a?.color, b?.color, t),
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:collection' show Queue;
import 'dart:math' as math;
......@@ -172,16 +170,16 @@ class BottomNavigationBar extends StatefulWidget {
/// [BottomNavigationBarType.fixed] and `false` if [type] is
/// [BottomNavigationBarType.shifting].
BottomNavigationBar({
Key key,
@required this.items,
Key? key,
required this.items,
this.onTap,
this.currentIndex = 0,
this.elevation,
this.type,
Color fixedColor,
Color? fixedColor,
this.backgroundColor,
this.iconSize = 24.0,
Color selectedItemColor,
Color? selectedItemColor,
this.unselectedItemColor,
this.selectedIconTheme,
this.unselectedIconTheme,
......@@ -221,7 +219,7 @@ class BottomNavigationBar extends StatefulWidget {
/// The stateful widget that creates the bottom navigation bar needs to keep
/// track of the index of the selected [BottomNavigationBarItem] and call
/// `setState` to rebuild the bottom navigation bar with the new [currentIndex].
final ValueChanged<int> onTap;
final ValueChanged<int>? onTap;
/// The index into [items] for the current active [BottomNavigationBarItem].
final int currentIndex;
......@@ -231,26 +229,26 @@ class BottomNavigationBar extends StatefulWidget {
/// If null, defaults to `8.0`.
///
/// {@macro flutter.material.material.elevation}
final double elevation;
final double? elevation;
/// Defines the layout and behavior of a [BottomNavigationBar].
///
/// See documentation for [BottomNavigationBarType] for information on the
/// meaning of different types.
final BottomNavigationBarType type;
final BottomNavigationBarType? type;
/// The value of [selectedItemColor].
///
/// This getter only exists for backwards compatibility, the
/// [selectedItemColor] property is preferred.
Color get fixedColor => selectedItemColor;
Color? get fixedColor => selectedItemColor;
/// The color of the [BottomNavigationBar] itself.
///
/// If [type] is [BottomNavigationBarType.shifting] and the
/// [items] have [BottomNavigationBarItem.backgroundColor] set, the [items]'
/// backgroundColor will splash and overwrite this color.
final Color backgroundColor;
final Color? backgroundColor;
/// The size of all of the [BottomNavigationBarItem] icons.
///
......@@ -261,13 +259,13 @@ class BottomNavigationBar extends StatefulWidget {
/// [BottomNavigationBarItem.title].
///
/// If null then the [ThemeData.primaryColor] is used.
final Color selectedItemColor;
final Color? selectedItemColor;
/// The color of the unselected [BottomNavigationBarItem.icon] and
/// [BottomNavigationBarItem.title]s.
///
/// If null then the [TextTheme.caption]'s color is used.
final Color unselectedItemColor;
final Color? unselectedItemColor;
/// The size, opacity, and color of the icon in the currently selected
/// [BottomNavigationBarItem.icon].
......@@ -278,7 +276,7 @@ class BottomNavigationBar extends StatefulWidget {
/// It this field is provided, it must contain non-null [IconThemeData.size]
/// and [IconThemeData.color] properties. Also, if this field is supplied,
/// [unselectedIconTheme] must be provided.
final IconThemeData selectedIconTheme;
final IconThemeData? selectedIconTheme;
/// The size, opacity, and color of the icon in the currently unselected
/// [BottomNavigationBarItem.icon]s.
......@@ -289,15 +287,15 @@ class BottomNavigationBar extends StatefulWidget {
/// It this field is provided, it must contain non-null [IconThemeData.size]
/// and [IconThemeData.color] properties. Also, if this field is supplied,
/// [unselectedIconTheme] must be provided.
final IconThemeData unselectedIconTheme;
final IconThemeData? unselectedIconTheme;
/// The [TextStyle] of the [BottomNavigationBarItem] labels when they are
/// selected.
final TextStyle selectedLabelStyle;
final TextStyle? selectedLabelStyle;
/// The [TextStyle] of the [BottomNavigationBarItem] labels when they are not
/// selected.
final TextStyle unselectedLabelStyle;
final TextStyle? unselectedLabelStyle;
/// The font size of the [BottomNavigationBarItem] labels when they are selected.
///
......@@ -317,7 +315,7 @@ class BottomNavigationBar extends StatefulWidget {
final double unselectedFontSize;
/// Whether the labels are shown for the selected [BottomNavigationBarItem].
final bool showUnselectedLabels;
final bool? showUnselectedLabels;
/// Whether the labels are shown for the unselected [BottomNavigationBarItem]s.
final bool showSelectedLabels;
......@@ -326,7 +324,7 @@ class BottomNavigationBar extends StatefulWidget {
/// tiles.
///
/// If this property is null, [SystemMouseCursors.click] will be used.
final MouseCursor mouseCursor;
final MouseCursor? mouseCursor;
@override
_BottomNavigationBarState createState() => _BottomNavigationBarState();
......@@ -344,14 +342,14 @@ class _BottomNavigationTile extends StatelessWidget {
this.colorTween,
this.flex,
this.selected = false,
@required this.selectedLabelStyle,
@required this.unselectedLabelStyle,
@required this.selectedIconTheme,
@required this.unselectedIconTheme,
required this.selectedLabelStyle,
required this.unselectedLabelStyle,
required this.selectedIconTheme,
required this.unselectedIconTheme,
this.showSelectedLabels,
this.showUnselectedLabels,
this.indexLabel,
@required this.mouseCursor,
required this.mouseCursor,
}) : assert(type != null),
assert(item != null),
assert(animation != null),
......@@ -364,17 +362,17 @@ class _BottomNavigationTile extends StatelessWidget {
final BottomNavigationBarItem item;
final Animation<double> animation;
final double iconSize;
final VoidCallback onTap;
final ColorTween colorTween;
final double flex;
final VoidCallback? onTap;
final ColorTween? colorTween;
final double? flex;
final bool selected;
final IconThemeData selectedIconTheme;
final IconThemeData unselectedIconTheme;
final IconThemeData? selectedIconTheme;
final IconThemeData? unselectedIconTheme;
final TextStyle selectedLabelStyle;
final TextStyle unselectedLabelStyle;
final String indexLabel;
final bool showSelectedLabels;
final bool showUnselectedLabels;
final String? indexLabel;
final bool? showSelectedLabels;
final bool? showUnselectedLabels;
final MouseCursor mouseCursor;
@override
......@@ -387,13 +385,13 @@ class _BottomNavigationTile extends StatelessWidget {
final BottomNavigationBarThemeData bottomTheme = BottomNavigationBarTheme.of(context);
final double selectedFontSize = selectedLabelStyle.fontSize;
final double selectedFontSize = selectedLabelStyle.fontSize!;
final double selectedIconSize = selectedIconTheme?.size
?? bottomTheme?.selectedIconTheme?.size
?? bottomTheme.selectedIconTheme?.size
?? iconSize;
final double unselectedIconSize = unselectedIconTheme?.size
?? bottomTheme?.unselectedIconTheme?.size
?? bottomTheme.unselectedIconTheme?.size
?? iconSize;
// The amount that the selected icon is bigger than the unselected icons,
......@@ -422,7 +420,7 @@ class _BottomNavigationTile extends StatelessWidget {
// =======
double bottomPadding;
double topPadding;
if (showSelectedLabels && !showUnselectedLabels) {
if (showSelectedLabels! && !showUnselectedLabels!) {
bottomPadding = Tween<double>(
begin: selectedIconDiff / 2.0,
end: selectedFontSize / 2.0 - unselectedIconDiff / 2.0,
......@@ -431,7 +429,7 @@ class _BottomNavigationTile extends StatelessWidget {
begin: selectedFontSize + selectedIconDiff / 2.0,
end: selectedFontSize / 2.0 - unselectedIconDiff / 2.0,
).evaluate(animation);
} else if (!showSelectedLabels && !showUnselectedLabels) {
} else if (!showSelectedLabels! && !showUnselectedLabels!) {
bottomPadding = Tween<double>(
begin: selectedIconDiff / 2.0,
end: unselectedIconDiff / 2.0,
......@@ -456,7 +454,7 @@ class _BottomNavigationTile extends StatelessWidget {
size = 1;
break;
case BottomNavigationBarType.shifting:
size = (flex * 1000.0).round();
size = (flex! * 1000.0).round();
break;
}
......@@ -471,7 +469,7 @@ class _BottomNavigationTile extends StatelessWidget {
mainAxisSize: MainAxisSize.min,
children: <Widget>[
_TileIcon(
colorTween: colorTween,
colorTween: colorTween!,
animation: animation,
iconSize: iconSize,
selected: selected,
......@@ -480,13 +478,13 @@ class _BottomNavigationTile extends StatelessWidget {
unselectedIconTheme: unselectedIconTheme ?? bottomTheme.unselectedIconTheme,
),
_Label(
colorTween: colorTween,
colorTween: colorTween!,
animation: animation,
item: item,
selectedLabelStyle: selectedLabelStyle ?? bottomTheme.selectedLabelStyle,
unselectedLabelStyle: unselectedLabelStyle ?? bottomTheme.unselectedLabelStyle,
showSelectedLabels: showSelectedLabels ?? bottomTheme.showUnselectedLabels,
showUnselectedLabels: showUnselectedLabels ?? bottomTheme.showUnselectedLabels,
selectedLabelStyle: selectedLabelStyle,
unselectedLabelStyle: unselectedLabelStyle,
showSelectedLabels: showSelectedLabels ?? bottomTheme.showUnselectedLabels!,
showUnselectedLabels: showUnselectedLabels ?? bottomTheme.showUnselectedLabels!,
),
],
),
......@@ -495,7 +493,7 @@ class _BottomNavigationTile extends StatelessWidget {
if (item.label != null) {
result = Tooltip(
message: item.label,
message: item.label!,
preferBelow: false,
verticalOffset: selectedIconSize + selectedFontSize,
child: result,
......@@ -525,14 +523,14 @@ class _BottomNavigationTile extends StatelessWidget {
class _TileIcon extends StatelessWidget {
const _TileIcon({
Key key,
@required this.colorTween,
@required this.animation,
@required this.iconSize,
@required this.selected,
@required this.item,
@required this.selectedIconTheme,
@required this.unselectedIconTheme,
Key? key,
required this.colorTween,
required this.animation,
required this.iconSize,
required this.selected,
required this.item,
required this.selectedIconTheme,
required this.unselectedIconTheme,
}) : assert(selected != null),
assert(item != null),
super(key: key);
......@@ -542,12 +540,12 @@ class _TileIcon extends StatelessWidget {
final double iconSize;
final bool selected;
final BottomNavigationBarItem item;
final IconThemeData selectedIconTheme;
final IconThemeData unselectedIconTheme;
final IconThemeData? selectedIconTheme;
final IconThemeData? unselectedIconTheme;
@override
Widget build(BuildContext context) {
final Color iconColor = colorTween.evaluate(animation);
final Color? iconColor = colorTween.evaluate(animation);
final IconThemeData defaultIconTheme = IconThemeData(
color: iconColor,
size: iconSize,
......@@ -573,14 +571,14 @@ class _TileIcon extends StatelessWidget {
class _Label extends StatelessWidget {
const _Label({
Key key,
@required this.colorTween,
@required this.animation,
@required this.item,
@required this.selectedLabelStyle,
@required this.unselectedLabelStyle,
@required this.showSelectedLabels,
@required this.showUnselectedLabels,
Key? key,
required this.colorTween,
required this.animation,
required this.item,
required this.selectedLabelStyle,
required this.unselectedLabelStyle,
required this.showSelectedLabels,
required this.showUnselectedLabels,
}) : assert(colorTween != null),
assert(animation != null),
assert(item != null),
......@@ -600,14 +598,14 @@ class _Label extends StatelessWidget {
@override
Widget build(BuildContext context) {
final double selectedFontSize = selectedLabelStyle.fontSize;
final double unselectedFontSize = unselectedLabelStyle.fontSize;
final double? selectedFontSize = selectedLabelStyle.fontSize;
final double? unselectedFontSize = unselectedLabelStyle.fontSize;
final TextStyle customStyle = TextStyle.lerp(
unselectedLabelStyle,
selectedLabelStyle,
animation.value,
);
)!;
Widget text = DefaultTextStyle.merge(
style: customStyle.copyWith(
fontSize: selectedFontSize,
......@@ -620,13 +618,13 @@ class _Label extends StatelessWidget {
transform: Matrix4.diagonal3(
Vector3.all(
Tween<double>(
begin: unselectedFontSize / selectedFontSize,
begin: unselectedFontSize! / selectedFontSize!,
end: 1.0,
).evaluate(animation),
),
),
alignment: Alignment.bottomCenter,
child: item.title ?? Text(item.label),
child: item.title ?? Text(item.label!),
),
);
......@@ -662,7 +660,7 @@ class _Label extends StatelessWidget {
if (item.label != null) {
// Do not grow text in bottom navigation bar when we can show a tooltip
// instead.
final MediaQueryData mediaQueryData = MediaQuery.of(context);
final MediaQueryData mediaQueryData = MediaQuery.of(context)!;
text = MediaQuery(
data: mediaQueryData.copyWith(
textScaleFactor: math.min(1.0, mediaQueryData.textScaleFactor),
......@@ -677,14 +675,14 @@ class _Label extends StatelessWidget {
class _BottomNavigationBarState extends State<BottomNavigationBar> with TickerProviderStateMixin {
List<AnimationController> _controllers = <AnimationController>[];
List<CurvedAnimation> _animations;
late List<CurvedAnimation> _animations;
// A queue of color splashes currently being animated.
final Queue<_Circle> _circles = Queue<_Circle>();
// Last splash circle's color, and the final color of the control after
// animation is complete.
Color _backgroundColor;
Color? _backgroundColor;
static final Animatable<double> _flexTween = Tween<double>(begin: 1.0, end: 1.5);
......@@ -735,8 +733,6 @@ class _BottomNavigationBarState extends State<BottomNavigationBar> with TickerPr
case BottomNavigationBarType.fixed:
return true;
}
assert(false);
return false;
}
@override
......@@ -769,7 +765,7 @@ class _BottomNavigationBarState extends State<BottomNavigationBar> with TickerPr
_Circle(
state: this,
index: index,
color: widget.items[index].backgroundColor,
color: widget.items[index].backgroundColor!,
vsync: this,
)..controller.addStatusListener(
(AnimationStatus status) {
......@@ -820,17 +816,17 @@ class _BottomNavigationBarState extends State<BottomNavigationBar> with TickerPr
// If the given [TextStyle] has a non-null `fontSize`, it should be used.
// Otherwise, the [selectedFontSize] parameter should be used.
static TextStyle _effectiveTextStyle(TextStyle textStyle, double fontSize) {
static TextStyle _effectiveTextStyle(TextStyle? textStyle, double fontSize) {
textStyle ??= const TextStyle();
// Prefer the font size on textStyle if present.
return textStyle.fontSize == null ? textStyle.copyWith(fontSize: fontSize) : textStyle;
}
List<Widget> _createTiles() {
final MaterialLocalizations localizations = MaterialLocalizations.of(context);
final MaterialLocalizations localizations = MaterialLocalizations.of(context)!;
assert(localizations != null);
final ThemeData themeData = Theme.of(context);
final ThemeData themeData = Theme.of(context)!;
final BottomNavigationBarThemeData bottomTheme = BottomNavigationBarTheme.of(context);
final TextStyle effectiveSelectedLabelStyle =
......@@ -860,7 +856,7 @@ class _BottomNavigationBarState extends State<BottomNavigationBar> with TickerPr
colorTween = ColorTween(
begin: widget.unselectedItemColor
?? bottomTheme.unselectedItemColor
?? themeData.textTheme.caption.color,
?? themeData.textTheme.caption!.color,
end: widget.selectedItemColor
?? bottomTheme.selectedItemColor
?? widget.fixedColor
......@@ -893,12 +889,12 @@ class _BottomNavigationBarState extends State<BottomNavigationBar> with TickerPr
unselectedLabelStyle: effectiveUnselectedLabelStyle,
onTap: () {
if (widget.onTap != null)
widget.onTap(i);
widget.onTap!(i);
},
colorTween: colorTween,
flex: _evaluateFlex(_animations[i]),
selected: i == widget.currentIndex,
showSelectedLabels: widget.showSelectedLabels ?? bottomTheme.showSelectedLabels,
showSelectedLabels: widget.showSelectedLabels,
showUnselectedLabels: widget.showUnselectedLabels ?? bottomTheme.showUnselectedLabels ?? _defaultShowUnselected,
indexLabel: localizations.tabLabel(tabIndex: i + 1, tabCount: widget.items.length),
mouseCursor: effectiveMouseCursor,
......@@ -927,8 +923,8 @@ class _BottomNavigationBarState extends State<BottomNavigationBar> with TickerPr
final BottomNavigationBarThemeData bottomTheme = BottomNavigationBarTheme.of(context);
// Labels apply up to _bottomMargin padding. Remainder is media padding.
final double additionalBottomPadding = math.max(MediaQuery.of(context).padding.bottom - widget.selectedFontSize / 2.0, 0.0);
Color backgroundColor;
final double additionalBottomPadding = math.max(MediaQuery.of(context)!.padding.bottom - widget.selectedFontSize / 2.0, 0.0);
Color? backgroundColor;
switch (_effectiveType) {
case BottomNavigationBarType.fixed:
backgroundColor = widget.backgroundColor ?? bottomTheme.backgroundColor;
......@@ -947,7 +943,7 @@ class _BottomNavigationBarState extends State<BottomNavigationBar> with TickerPr
child: CustomPaint(
painter: _RadialPainter(
circles: _circles.toList(),
textDirection: Directionality.of(context),
textDirection: Directionality.of(context)!,
),
child: Material( // Splashes.
type: MaterialType.transparency,
......@@ -970,10 +966,10 @@ class _BottomNavigationBarState extends State<BottomNavigationBar> with TickerPr
// Describes an animating color splash circle.
class _Circle {
_Circle({
@required this.state,
@required this.index,
@required this.color,
@required TickerProvider vsync,
required this.state,
required this.index,
required this.color,
required TickerProvider vsync,
}) : assert(state != null),
assert(index != null),
assert(color != null) {
......@@ -991,8 +987,8 @@ class _Circle {
final _BottomNavigationBarState state;
final int index;
final Color color;
AnimationController controller;
CurvedAnimation animation;
late AnimationController controller;
late CurvedAnimation animation;
double get horizontalLeadingOffset {
double weightSum(Iterable<Animation<double>> animations) {
......@@ -1017,8 +1013,8 @@ class _Circle {
// Paints the animating color splash circles.
class _RadialPainter extends CustomPainter {
_RadialPainter({
@required this.circles,
@required this.textDirection,
required this.circles,
required this.textDirection,
}) : assert(circles != null),
assert(textDirection != null);
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:ui' show lerpDouble;
import 'package:flutter/foundation.dart';
......@@ -50,78 +48,78 @@ class BottomNavigationBarThemeData with Diagnosticable {
/// The color of the [BottomNavigationBar] itself.
///
/// See [BottomNavigationBar.backgroundColor].
final Color backgroundColor;
final Color? backgroundColor;
/// The z-coordinate of the [BottomNavigationBar].
///
/// See [BottomNavigationBar.elevation].
final double elevation;
final double? elevation;
/// The size, opacity, and color of the icon in the currently selected
/// [BottomNavigationBarItem.icon].
///
/// See [BottomNavigationBar.selectedIconTheme].
final IconThemeData selectedIconTheme;
final IconThemeData? selectedIconTheme;
/// The size, opacity, and color of the icon in the currently unselected
/// [BottomNavigationBarItem.icon]s.
///
/// See [BottomNavigationBar.unselectedIconTheme].
final IconThemeData unselectedIconTheme;
final IconThemeData? unselectedIconTheme;
/// The color of the selected [BottomNavigationBarItem.icon] and
/// [BottomNavigationBarItem.title].
///
/// See [BottomNavigationBar.selectedItemColor].
final Color selectedItemColor;
final Color? selectedItemColor;
/// The color of the unselected [BottomNavigationBarItem.icon] and
/// [BottomNavigationBarItem.title]s.
///
/// See [BottomNavigationBar.unselectedItemColor].
final Color unselectedItemColor;
final Color? unselectedItemColor;
/// The [TextStyle] of the [BottomNavigationBarItem] labels when they are
/// selected.
///
/// See [BottomNavigationBar.selectedLabelStyle].
final TextStyle selectedLabelStyle;
final TextStyle? selectedLabelStyle;
/// The [TextStyle] of the [BottomNavigationBarItem] labels when they are not
/// selected.
///
/// See [BottomNavigationBar.unselectedLabelStyle].
final TextStyle unselectedLabelStyle;
final TextStyle? unselectedLabelStyle;
/// Whether the labels are shown for the unselected [BottomNavigationBarItem]s.
///
/// See [BottomNavigationBar.showSelectedLabels].
final bool showSelectedLabels;
final bool? showSelectedLabels;
/// Whether the labels are shown for the selected [BottomNavigationBarItem].
///
/// See [BottomNavigationBar.showUnselectedLabels].
final bool showUnselectedLabels;
final bool? showUnselectedLabels;
/// Defines the layout and behavior of a [BottomNavigationBar].
///
/// See [BottomNavigationBar.type].
final BottomNavigationBarType type;
final BottomNavigationBarType? type;
/// Creates a copy of this object but with the given fields replaced with the
/// new values.
BottomNavigationBarThemeData copyWith({
Color backgroundColor,
double elevation,
IconThemeData selectedIconTheme,
IconThemeData unselectedIconTheme,
Color selectedItemColor,
Color unselectedItemColor,
TextStyle selectedLabelStyle,
TextStyle unselectedLabelStyle,
bool showSelectedLabels,
bool showUnselectedLabels,
BottomNavigationBarType type,
Color? backgroundColor,
double? elevation,
IconThemeData? selectedIconTheme,
IconThemeData? unselectedIconTheme,
Color? selectedItemColor,
Color? unselectedItemColor,
TextStyle? selectedLabelStyle,
TextStyle? unselectedLabelStyle,
bool? showSelectedLabels,
bool? showUnselectedLabels,
BottomNavigationBarType? type,
}) {
return BottomNavigationBarThemeData(
backgroundColor: backgroundColor ?? this.backgroundColor,
......@@ -143,7 +141,7 @@ class BottomNavigationBarThemeData with Diagnosticable {
/// The argument `t` must not be null.
///
/// {@macro dart.ui.shadow.lerp}
static BottomNavigationBarThemeData lerp(BottomNavigationBarThemeData a, BottomNavigationBarThemeData b, double t) {
static BottomNavigationBarThemeData lerp(BottomNavigationBarThemeData? a, BottomNavigationBarThemeData? b, double t) {
assert(t != null);
return BottomNavigationBarThemeData(
backgroundColor: Color.lerp(a?.backgroundColor, b?.backgroundColor, t),
......@@ -235,9 +233,9 @@ class BottomNavigationBarTheme extends InheritedWidget {
///
/// The [data] must not be null.
const BottomNavigationBarTheme({
Key key,
@required this.data,
Widget child,
Key? key,
required this.data,
required Widget child,
}) : assert(data != null), super(key: key, child: child);
/// The properties used for all descendant [BottomNavigationBar] widgets.
......@@ -254,8 +252,8 @@ class BottomNavigationBarTheme extends InheritedWidget {
/// BottomNavigationBarThemeData theme = BottomNavigationBarTheme.of(context);
/// ```
static BottomNavigationBarThemeData of(BuildContext context) {
final BottomNavigationBarTheme bottomNavTheme = context.dependOnInheritedWidgetOfExactType<BottomNavigationBarTheme>();
return bottomNavTheme?.data ?? Theme.of(context).bottomNavigationBarTheme;
final BottomNavigationBarTheme? bottomNavTheme = context.dependOnInheritedWidgetOfExactType<BottomNavigationBarTheme>();
return bottomNavTheme?.data ?? Theme.of(context)!.bottomNavigationBarTheme;
}
@override
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:ui' show lerpDouble;
import 'package:flutter/foundation.dart';
......@@ -35,7 +33,7 @@ typedef BottomSheetDragStartHandler = void Function(DragStartDetails details);
/// Used by [BottomSheet.onDragEnd].
typedef BottomSheetDragEndHandler = void Function(
DragEndDetails details, {
bool isClosing,
required bool isClosing,
});
/// A material design bottom sheet.
......@@ -72,7 +70,7 @@ class BottomSheet extends StatefulWidget {
/// [ScaffoldState.showBottomSheet], for persistent bottom sheets, or by
/// [showModalBottomSheet], for modal bottom sheets.
const BottomSheet({
Key key,
Key? key,
this.animationController,
this.enableDrag = true,
this.onDragStart,
......@@ -81,8 +79,8 @@ class BottomSheet extends StatefulWidget {
this.elevation,
this.shape,
this.clipBehavior,
@required this.onClosing,
@required this.builder,
required this.onClosing,
required this.builder,
}) : assert(enableDrag != null),
assert(onClosing != null),
assert(builder != null),
......@@ -94,7 +92,7 @@ class BottomSheet extends StatefulWidget {
///
/// The BottomSheet widget will manipulate the position of this animation, it
/// is not just a passive observer.
final AnimationController animationController;
final AnimationController? animationController;
/// Called when the bottom sheet begins to close.
///
......@@ -120,7 +118,7 @@ class BottomSheet extends StatefulWidget {
///
/// Would typically be used to change the bottom sheet animation curve so
/// that it tracks the user's finger accurately.
final BottomSheetDragStartHandler onDragStart;
final BottomSheetDragStartHandler? onDragStart;
/// Called when the user stops dragging the bottom sheet, if [enableDrag]
/// is true.
......@@ -128,28 +126,28 @@ class BottomSheet extends StatefulWidget {
/// Would typically be used to reset the bottom sheet animation curve, so
/// that it animates non-linearly. Called before [onClosing] if the bottom
/// sheet is closing.
final BottomSheetDragEndHandler onDragEnd;
final BottomSheetDragEndHandler? onDragEnd;
/// The bottom sheet's background color.
///
/// Defines the bottom sheet's [Material.color].
///
/// Defaults to null and falls back to [Material]'s default.
final Color backgroundColor;
final Color? backgroundColor;
/// The z-coordinate at which to place this material relative to its parent.
///
/// This controls the size of the shadow below the material.
///
/// Defaults to 0. The value is non-negative.
final double elevation;
final double? elevation;
/// The shape of the bottom sheet.
///
/// Defines the bottom sheet's [Material.shape].
///
/// Defaults to null and falls back to [Material]'s default.
final ShapeBorder shape;
final ShapeBorder? shape;
/// {@macro flutter.widgets.Clip}
///
......@@ -163,7 +161,7 @@ class BottomSheet extends StatefulWidget {
/// If this property is null then [BottomSheetThemeData.clipBehavior] of
/// [ThemeData.bottomSheetTheme] is used. If that's null then the behavior
/// will be [Clip.none].
final Clip clipBehavior;
final Clip? clipBehavior;
@override
_BottomSheetState createState() => _BottomSheetState();
......@@ -189,15 +187,15 @@ class _BottomSheetState extends State<BottomSheet> {
final GlobalKey _childKey = GlobalKey(debugLabel: 'BottomSheet child');
double get _childHeight {
final RenderBox renderBox = _childKey.currentContext.findRenderObject() as RenderBox;
final RenderBox renderBox = _childKey.currentContext!.findRenderObject() as RenderBox;
return renderBox.size.height;
}
bool get _dismissUnderway => widget.animationController.status == AnimationStatus.reverse;
bool get _dismissUnderway => widget.animationController!.status == AnimationStatus.reverse;
void _handleDragStart(DragStartDetails details) {
if (widget.onDragStart != null) {
widget.onDragStart(details);
widget.onDragStart!(details);
}
}
......@@ -205,7 +203,7 @@ class _BottomSheetState extends State<BottomSheet> {
assert(widget.enableDrag);
if (_dismissUnderway)
return;
widget.animationController.value -= details.primaryDelta / (_childHeight ?? details.primaryDelta);
widget.animationController!.value -= details.primaryDelta! / _childHeight;
}
void _handleDragEnd(DragEndDetails details) {
......@@ -215,22 +213,22 @@ class _BottomSheetState extends State<BottomSheet> {
bool isClosing = false;
if (details.velocity.pixelsPerSecond.dy > _minFlingVelocity) {
final double flingVelocity = -details.velocity.pixelsPerSecond.dy / _childHeight;
if (widget.animationController.value > 0.0) {
widget.animationController.fling(velocity: flingVelocity);
if (widget.animationController!.value > 0.0) {
widget.animationController!.fling(velocity: flingVelocity);
}
if (flingVelocity < 0.0) {
isClosing = true;
}
} else if (widget.animationController.value < _closeProgressThreshold) {
if (widget.animationController.value > 0.0)
widget.animationController.fling(velocity: -1.0);
} else if (widget.animationController!.value < _closeProgressThreshold) {
if (widget.animationController!.value > 0.0)
widget.animationController!.fling(velocity: -1.0);
isClosing = true;
} else {
widget.animationController.forward();
widget.animationController!.forward();
}
if (widget.onDragEnd != null) {
widget.onDragEnd(
widget.onDragEnd!(
details,
isClosing: isClosing,
);
......@@ -250,10 +248,10 @@ class _BottomSheetState extends State<BottomSheet> {
@override
Widget build(BuildContext context) {
final BottomSheetThemeData bottomSheetTheme = Theme.of(context).bottomSheetTheme;
final Color color = widget.backgroundColor ?? bottomSheetTheme.backgroundColor;
final BottomSheetThemeData bottomSheetTheme = Theme.of(context)!.bottomSheetTheme;
final Color? color = widget.backgroundColor ?? bottomSheetTheme.backgroundColor;
final double elevation = widget.elevation ?? bottomSheetTheme.elevation ?? 0;
final ShapeBorder shape = widget.shape ?? bottomSheetTheme.shape;
final ShapeBorder? shape = widget.shape ?? bottomSheetTheme.shape;
final Clip clipBehavior = widget.clipBehavior ?? bottomSheetTheme.clipBehavior ?? Clip.none;
final Widget bottomSheet = Material(
......@@ -314,7 +312,7 @@ class _ModalBottomSheetLayout extends SingleChildLayoutDelegate {
class _ModalBottomSheet<T> extends StatefulWidget {
const _ModalBottomSheet({
Key key,
Key? key,
this.route,
this.backgroundColor,
this.elevation,
......@@ -326,12 +324,12 @@ class _ModalBottomSheet<T> extends StatefulWidget {
assert(enableDrag != null),
super(key: key);
final _ModalBottomSheetRoute<T> route;
final _ModalBottomSheetRoute<T>? route;
final bool isScrollControlled;
final Color backgroundColor;
final double elevation;
final ShapeBorder shape;
final Clip clipBehavior;
final Color? backgroundColor;
final double? elevation;
final ShapeBorder? shape;
final Clip? clipBehavior;
final bool enableDrag;
@override
......@@ -342,7 +340,7 @@ class _ModalBottomSheetState<T> extends State<_ModalBottomSheet<T>> {
ParametricCurve<double> animationCurve = _modalBottomSheetCurve;
String _getRouteLabel(MaterialLocalizations localizations) {
switch (Theme.of(context).platform) {
switch (Theme.of(context)!.platform) {
case TargetPlatform.iOS:
case TargetPlatform.macOS:
return '';
......@@ -352,7 +350,6 @@ class _ModalBottomSheetState<T> extends State<_ModalBottomSheet<T>> {
case TargetPlatform.windows:
return localizations.dialogLabel;
}
return null;
}
void handleDragStart(DragStartDetails details) {
......@@ -360,10 +357,10 @@ class _ModalBottomSheetState<T> extends State<_ModalBottomSheet<T>> {
animationCurve = Curves.linear;
}
void handleDragEnd(DragEndDetails details, {bool isClosing}) {
void handleDragEnd(DragEndDetails details, {bool? isClosing}) {
// Allow the bottom sheet to animate smoothly from its current position.
animationCurve = _BottomSheetSuspendedCurve(
widget.route.animation.value,
widget.route!.animation!.value,
curve: _modalBottomSheetCurve,
);
}
......@@ -372,20 +369,20 @@ class _ModalBottomSheetState<T> extends State<_ModalBottomSheet<T>> {
Widget build(BuildContext context) {
assert(debugCheckHasMediaQuery(context));
assert(debugCheckHasMaterialLocalizations(context));
final MediaQueryData mediaQuery = MediaQuery.of(context);
final MaterialLocalizations localizations = MaterialLocalizations.of(context);
final MediaQueryData? mediaQuery = MediaQuery.of(context);
final MaterialLocalizations localizations = MaterialLocalizations.of(context)!;
final String routeLabel = _getRouteLabel(localizations);
return AnimatedBuilder(
animation: widget.route.animation,
animation: widget.route!.animation!,
child: BottomSheet(
animationController: widget.route._animationController,
animationController: widget.route!._animationController,
onClosing: () {
if (widget.route.isCurrent) {
if (widget.route!.isCurrent) {
Navigator.pop(context);
}
},
builder: widget.route.builder,
builder: widget.route!.builder!,
backgroundColor: widget.backgroundColor,
elevation: widget.elevation,
shape: widget.shape,
......@@ -394,11 +391,11 @@ class _ModalBottomSheetState<T> extends State<_ModalBottomSheet<T>> {
onDragStart: handleDragStart,
onDragEnd: handleDragEnd,
),
builder: (BuildContext context, Widget child) {
builder: (BuildContext context, Widget? child) {
// Disable the initial animation when accessible navigation is on so
// that the semantics are added to the tree at the correct time.
final double animationValue = animationCurve.transform(
mediaQuery.accessibleNavigation ? 1.0 : widget.route.animation.value
mediaQuery!.accessibleNavigation ? 1.0 : widget.route!.animation!.value
);
return Semantics(
scopesRoute: true,
......@@ -429,21 +426,21 @@ class _ModalBottomSheetRoute<T> extends PopupRoute<T> {
this.modalBarrierColor,
this.isDismissible = true,
this.enableDrag = true,
@required this.isScrollControlled,
RouteSettings settings,
required this.isScrollControlled,
RouteSettings? settings,
}) : assert(isScrollControlled != null),
assert(isDismissible != null),
assert(enableDrag != null),
super(settings: settings);
final WidgetBuilder builder;
final ThemeData theme;
final WidgetBuilder? builder;
final ThemeData? theme;
final bool isScrollControlled;
final Color backgroundColor;
final double elevation;
final ShapeBorder shape;
final Clip clipBehavior;
final Color modalBarrierColor;
final Color? backgroundColor;
final double? elevation;
final ShapeBorder? shape;
final Clip? clipBehavior;
final Color? modalBarrierColor;
final bool isDismissible;
final bool enableDrag;
......@@ -457,23 +454,23 @@ class _ModalBottomSheetRoute<T> extends PopupRoute<T> {
bool get barrierDismissible => isDismissible;
@override
final String barrierLabel;
final String? barrierLabel;
@override
Color get barrierColor => modalBarrierColor ?? Colors.black54;
AnimationController _animationController;
AnimationController? _animationController;
@override
AnimationController createAnimationController() {
assert(_animationController == null);
_animationController = BottomSheet.createAnimationController(navigator.overlay);
return _animationController;
_animationController = BottomSheet.createAnimationController(navigator!.overlay!);
return _animationController!;
}
@override
Widget buildPage(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
final BottomSheetThemeData sheetTheme = theme?.bottomSheetTheme ?? Theme.of(context).bottomSheetTheme;
final BottomSheetThemeData sheetTheme = theme?.bottomSheetTheme ?? Theme.of(context)!.bottomSheetTheme;
// By definition, the bottom sheet is aligned to the bottom of the page
// and isn't exposed to the top padding of the MediaQuery.
Widget bottomSheet = MediaQuery.removePadding(
......@@ -481,8 +478,8 @@ class _ModalBottomSheetRoute<T> extends PopupRoute<T> {
removeTop: true,
child: _ModalBottomSheet<T>(
route: this,
backgroundColor: backgroundColor ?? sheetTheme?.modalBackgroundColor ?? sheetTheme?.backgroundColor,
elevation: elevation ?? sheetTheme?.modalElevation ?? sheetTheme?.elevation,
backgroundColor: backgroundColor ?? sheetTheme.modalBackgroundColor ?? sheetTheme.backgroundColor,
elevation: elevation ?? sheetTheme.modalElevation ?? sheetTheme.elevation,
shape: shape,
clipBehavior: clipBehavior,
isScrollControlled: isScrollControlled,
......@@ -490,7 +487,7 @@ class _ModalBottomSheetRoute<T> extends PopupRoute<T> {
),
);
if (theme != null)
bottomSheet = Theme(data: theme, child: bottomSheet);
bottomSheet = Theme(data: theme!, child: bottomSheet);
return bottomSheet;
}
}
......@@ -544,7 +541,7 @@ class _BottomSheetSuspendedCurve extends ParametricCurve<double> {
final double curveProgress = (t - startingPoint) / (1 - startingPoint);
final double transformed = curve.transform(curveProgress);
return lerpDouble(startingPoint, 1, transformed);
return lerpDouble(startingPoint, 1, transformed)!;
}
@override
......@@ -648,18 +645,18 @@ class _BottomSheetSuspendedCurve extends ParametricCurve<double> {
/// that grows and then becomes scrollable once it reaches its maximum size.
/// * <https://material.io/design/components/sheets-bottom.html#modal-bottom-sheet>
Future<T> showModalBottomSheet<T>({
@required BuildContext context,
@required WidgetBuilder builder,
Color backgroundColor,
double elevation,
ShapeBorder shape,
Clip clipBehavior,
Color barrierColor,
required BuildContext context,
required WidgetBuilder builder,
Color? backgroundColor,
double? elevation,
ShapeBorder? shape,
Clip? clipBehavior,
Color? barrierColor,
bool isScrollControlled = false,
bool useRootNavigator = false,
bool isDismissible = true,
bool enableDrag = true,
RouteSettings routeSettings,
RouteSettings? routeSettings,
}) {
assert(context != null);
assert(builder != null);
......@@ -670,11 +667,11 @@ Future<T> showModalBottomSheet<T>({
assert(debugCheckHasMediaQuery(context));
assert(debugCheckHasMaterialLocalizations(context));
return Navigator.of(context, rootNavigator: useRootNavigator).push(_ModalBottomSheetRoute<T>(
return Navigator.of(context, rootNavigator: useRootNavigator)!.push(_ModalBottomSheetRoute<T>(
builder: builder,
theme: Theme.of(context, shadowThemeOnly: true),
isScrollControlled: isScrollControlled,
barrierLabel: MaterialLocalizations.of(context).modalBarrierDismissLabel,
barrierLabel: MaterialLocalizations.of(context)!.modalBarrierDismissLabel,
backgroundColor: backgroundColor,
elevation: elevation,
shape: shape,
......@@ -726,18 +723,18 @@ Future<T> showModalBottomSheet<T>({
/// * [Scaffold.of], for information about how to obtain the [BuildContext].
/// * <https://material.io/design/components/sheets-bottom.html#standard-bottom-sheet>
PersistentBottomSheetController<T> showBottomSheet<T>({
@required BuildContext context,
@required WidgetBuilder builder,
Color backgroundColor,
double elevation,
ShapeBorder shape,
Clip clipBehavior,
required BuildContext context,
required WidgetBuilder builder,
Color? backgroundColor,
double? elevation,
ShapeBorder? shape,
Clip? clipBehavior,
}) {
assert(context != null);
assert(builder != null);
assert(debugCheckHasScaffold(context));
return Scaffold.of(context).showBottomSheet<T>(
return Scaffold.of(context)!.showBottomSheet<T>(
builder,
backgroundColor: backgroundColor,
elevation: elevation,
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:math' as math;
import 'package:flutter/foundation.dart';
......@@ -51,8 +49,8 @@ class RawMaterialButton extends StatefulWidget {
/// [elevation], [focusElevation], [hoverElevation], [highlightElevation], and
/// [disabledElevation] must be non-negative.
const RawMaterialButton({
Key key,
@required this.onPressed,
Key? key,
required this.onPressed,
this.onLongPress,
this.onHighlightChanged,
this.mouseCursor,
......@@ -75,7 +73,7 @@ class RawMaterialButton extends StatefulWidget {
this.clipBehavior = Clip.none,
this.focusNode,
this.autofocus = false,
MaterialTapTargetSize materialTapTargetSize,
MaterialTapTargetSize? materialTapTargetSize,
this.child,
this.enableFeedback = true,
}) : materialTapTargetSize = materialTapTargetSize ?? MaterialTapTargetSize.padded,
......@@ -99,7 +97,7 @@ class RawMaterialButton extends StatefulWidget {
/// See also:
///
/// * [enabled], which is true if the button is enabled.
final VoidCallback onPressed;
final VoidCallback? onPressed;
/// Called when the button is long-pressed.
///
......@@ -108,7 +106,7 @@ class RawMaterialButton extends StatefulWidget {
/// See also:
///
/// * [enabled], which is true if the button is enabled.
final VoidCallback onLongPress;
final VoidCallback? onLongPress;
/// Called by the underlying [InkWell] widget's [InkWell.onHighlightChanged]
/// callback.
......@@ -116,7 +114,7 @@ class RawMaterialButton extends StatefulWidget {
/// If [onPressed] changes from null to non-null while a gesture is ongoing,
/// this can fire during the build phase (in which case calling
/// [State.setState] is not allowed).
final ValueChanged<bool> onHighlightChanged;
final ValueChanged<bool>? onHighlightChanged;
/// {@template flutter.material.button.mouseCursor}
/// The cursor for a mouse pointer when it enters or is hovering over the
......@@ -132,7 +130,7 @@ class RawMaterialButton extends StatefulWidget {
///
/// If this property is null, [MaterialStateMouseCursor.clickable] will be used.
/// {@endtemplate}
final MouseCursor mouseCursor;
final MouseCursor? mouseCursor;
/// Defines the default text style, with [Material.textStyle], for the
/// button's [child].
......@@ -144,22 +142,22 @@ class RawMaterialButton extends StatefulWidget {
/// * [MaterialState.hovered].
/// * [MaterialState.focused].
/// * [MaterialState.disabled].
final TextStyle textStyle;
final TextStyle? textStyle;
/// The color of the button's [Material].
final Color fillColor;
final Color? fillColor;
/// The color for the button's [Material] when it has the input focus.
final Color focusColor;
final Color? focusColor;
/// The color for the button's [Material] when a pointer is hovering over it.
final Color hoverColor;
final Color? hoverColor;
/// The highlight color for the button's [InkWell].
final Color highlightColor;
final Color? highlightColor;
/// The splash color for the button's [InkWell].
final Color splashColor;
final Color? splashColor;
/// The elevation for the button's [Material] when the button
/// is [enabled] but not pressed.
......@@ -275,7 +273,7 @@ class RawMaterialButton extends StatefulWidget {
final Duration animationDuration;
/// Typically the button's label.
final Widget child;
final Widget? child;
/// Whether the button is enabled or disabled.
///
......@@ -293,7 +291,7 @@ class RawMaterialButton extends StatefulWidget {
final MaterialTapTargetSize materialTapTargetSize;
/// {@macro flutter.widgets.Focus.focusNode}
final FocusNode focusNode;
final FocusNode? focusNode;
/// {@macro flutter.widgets.Focus.autofocus}
final bool autofocus;
......@@ -334,7 +332,7 @@ class _RawMaterialButtonState extends State<RawMaterialButton> {
setState(() {
_updateState(MaterialState.pressed, value);
if (widget.onHighlightChanged != null) {
widget.onHighlightChanged(value);
widget.onHighlightChanged!(value);
}
});
}
......@@ -395,11 +393,11 @@ class _RawMaterialButtonState extends State<RawMaterialButton> {
@override
Widget build(BuildContext context) {
final Color effectiveTextColor = MaterialStateProperty.resolveAs<Color>(widget.textStyle?.color, _states);
final ShapeBorder effectiveShape = MaterialStateProperty.resolveAs<ShapeBorder>(widget.shape, _states);
final Color? effectiveTextColor = MaterialStateProperty.resolveAs<Color>(widget.textStyle?.color, _states);
final ShapeBorder? effectiveShape = MaterialStateProperty.resolveAs<ShapeBorder>(widget.shape, _states);
final Offset densityAdjustment = widget.visualDensity.baseSizeAdjustment;
final BoxConstraints effectiveConstraints = widget.visualDensity.effectiveConstraints(widget.constraints);
final MouseCursor effectiveMouseCursor = MaterialStateProperty.resolveAs<MouseCursor>(
final MouseCursor? effectiveMouseCursor = MaterialStateProperty.resolveAs<MouseCursor>(
widget.mouseCursor ?? MaterialStateMouseCursor.clickable,
_states,
);
......@@ -487,9 +485,9 @@ class _RawMaterialButtonState extends State<RawMaterialButton> {
/// "tap target", but not its material or its ink splashes.
class _InputPadding extends SingleChildRenderObjectWidget {
const _InputPadding({
Key key,
Widget child,
this.minSize,
Key? key,
Widget? child,
required this.minSize,
}) : super(key: key, child: child);
final Size minSize;
......@@ -506,7 +504,7 @@ class _InputPadding extends SingleChildRenderObjectWidget {
}
class _RenderInputPadding extends RenderShiftedBox {
_RenderInputPadding(this._minSize, [RenderBox child]) : super(child);
_RenderInputPadding(this._minSize, [RenderBox? child]) : super(child);
Size get minSize => _minSize;
Size _minSize;
......@@ -520,58 +518,57 @@ class _RenderInputPadding extends RenderShiftedBox {
@override
double computeMinIntrinsicWidth(double height) {
if (child != null)
return math.max(child.getMinIntrinsicWidth(height), minSize.width);
return math.max(child!.getMinIntrinsicWidth(height), minSize.width);
return 0.0;
}
@override
double computeMinIntrinsicHeight(double width) {
if (child != null)
return math.max(child.getMinIntrinsicHeight(width), minSize.height);
return math.max(child!.getMinIntrinsicHeight(width), minSize.height);
return 0.0;
}
@override
double computeMaxIntrinsicWidth(double height) {
if (child != null)
return math.max(child.getMaxIntrinsicWidth(height), minSize.width);
return math.max(child!.getMaxIntrinsicWidth(height), minSize.width);
return 0.0;
}
@override
double computeMaxIntrinsicHeight(double width) {
if (child != null)
return math.max(child.getMaxIntrinsicHeight(width), minSize.height);
return math.max(child!.getMaxIntrinsicHeight(width), minSize.height);
return 0.0;
}
@override
void performLayout() {
final BoxConstraints constraints = this.constraints;
if (child != null) {
child.layout(constraints, parentUsesSize: true);
final double height = math.max(child.size.width, minSize.width);
final double width = math.max(child.size.height, minSize.height);
child!.layout(constraints, parentUsesSize: true);
final double height = math.max(child!.size.width, minSize.width);
final double width = math.max(child!.size.height, minSize.height);
size = constraints.constrain(Size(height, width));
final BoxParentData childParentData = child.parentData as BoxParentData;
childParentData.offset = Alignment.center.alongOffset(size - child.size as Offset);
final BoxParentData childParentData = child!.parentData as BoxParentData;
childParentData.offset = Alignment.center.alongOffset(size - child!.size as Offset);
} else {
size = Size.zero;
}
}
@override
bool hitTest(BoxHitTestResult result, { Offset position }) {
bool hitTest(BoxHitTestResult result, { required Offset position }) {
if (super.hitTest(result, position: position)) {
return true;
}
final Offset center = child.size.center(Offset.zero);
final Offset center = child!.size.center(Offset.zero);
return result.addWithRawTransform(
transform: MatrixUtils.forceToPoint(center),
position: center,
hitTest: (BoxHitTestResult result, Offset position) {
hitTest: (BoxHitTestResult result, Offset? position) {
assert(position == center);
return child.hitTest(result, position: center);
return child!.hitTest(result, position: center);
},
);
}
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'package:flutter/widgets.dart';
import 'package:flutter/rendering.dart';
......@@ -56,7 +54,7 @@ class ButtonBar extends StatelessWidget {
/// Both [buttonMinWidth] and [buttonHeight] must be non-negative if they
/// are not null.
const ButtonBar({
Key key,
Key? key,
this.alignment,
this.mainAxisSize,
this.buttonTextTheme,
......@@ -77,13 +75,13 @@ class ButtonBar extends StatelessWidget {
///
/// If null then it will use [ButtonBarThemeData.alignment]. If that is null,
/// it will default to [MainAxisAlignment.end].
final MainAxisAlignment alignment;
final MainAxisAlignment? alignment;
/// How much horizontal space is available. See [Row.mainAxisSize].
///
/// If null then it will use the surrounding [ButtonBarThemeData.mainAxisSize].
/// If that is null, it will default to [MainAxisSize.max].
final MainAxisSize mainAxisSize;
final MainAxisSize? mainAxisSize;
/// Overrides the surrounding [ButtonBarThemeData.buttonTextTheme] to define a
/// button's base colors, size, internal padding and shape.
......@@ -91,21 +89,21 @@ class ButtonBar extends StatelessWidget {
/// If null then it will use the surrounding
/// [ButtonBarThemeData.buttonTextTheme]. If that is null, it will default to
/// [ButtonTextTheme.primary].
final ButtonTextTheme buttonTextTheme;
final ButtonTextTheme? buttonTextTheme;
/// Overrides the surrounding [ButtonThemeData.minWidth] to define a button's
/// minimum width.
///
/// If null then it will use the surrounding [ButtonBarThemeData.buttonMinWidth].
/// If that is null, it will default to 64.0 logical pixels.
final double buttonMinWidth;
final double? buttonMinWidth;
/// Overrides the surrounding [ButtonThemeData.height] to define a button's
/// minimum height.
///
/// If null then it will use the surrounding [ButtonBarThemeData.buttonHeight].
/// If that is null, it will default to 36.0 logical pixels.
final double buttonHeight;
final double? buttonHeight;
/// Overrides the surrounding [ButtonThemeData.padding] to define the padding
/// for a button's child (typically the button's label).
......@@ -113,14 +111,14 @@ class ButtonBar extends StatelessWidget {
/// If null then it will use the surrounding [ButtonBarThemeData.buttonPadding].
/// If that is null, it will default to 8.0 logical pixels on the left
/// and right.
final EdgeInsetsGeometry buttonPadding;
final EdgeInsetsGeometry? buttonPadding;
/// Overrides the surrounding [ButtonThemeData.alignedDropdown] to define whether
/// a [DropdownButton] menu's width will match the button's width.
///
/// If null then it will use the surrounding [ButtonBarThemeData.buttonAlignedDropdown].
/// If that is null, it will default to false.
final bool buttonAlignedDropdown;
final bool? buttonAlignedDropdown;
/// Defines whether a [ButtonBar] should size itself with a minimum size
/// constraint or with padding.
......@@ -129,7 +127,7 @@ class ButtonBar extends StatelessWidget {
///
/// If null then it will use the surrounding [ButtonBarThemeData.layoutBehavior].
/// If that is null, it will default [ButtonBarLayoutBehavior.padded].
final ButtonBarLayoutBehavior layoutBehavior;
final ButtonBarLayoutBehavior? layoutBehavior;
/// Defines the vertical direction of a [ButtonBar]'s children if it
/// overflows.
......@@ -145,7 +143,7 @@ class ButtonBar extends StatelessWidget {
/// If null then it will use the surrounding
/// [ButtonBarThemeData.overflowDirection]. If that is null, it will
/// default to [VerticalDirection.down].
final VerticalDirection overflowDirection;
final VerticalDirection? overflowDirection;
/// The spacing between buttons when the button bar overflows.
///
......@@ -161,7 +159,7 @@ class ButtonBar extends StatelessWidget {
///
/// If null then no spacing will be added in between buttons in
/// an overflow state.
final double overflowButtonSpacing;
final double? overflowButtonSpacing;
/// The buttons to arrange horizontally.
///
......@@ -216,8 +214,6 @@ class ButtonBar extends StatelessWidget {
child: child,
);
}
assert(false);
return null;
}
}
......@@ -239,14 +235,14 @@ class _ButtonBarRow extends Flex {
/// Creates a button bar that attempts to display in a row, but displays in
/// a column if there is insufficient horizontal space.
_ButtonBarRow({
List<Widget> children,
required List<Widget> children,
Axis direction = Axis.horizontal,
MainAxisSize mainAxisSize = MainAxisSize.max,
MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start,
CrossAxisAlignment crossAxisAlignment = CrossAxisAlignment.center,
TextDirection textDirection,
TextDirection? textDirection,
VerticalDirection overflowDirection = VerticalDirection.down,
TextBaseline textBaseline,
TextBaseline? textBaseline,
this.overflowButtonSpacing,
}) : super(
children: children,
......@@ -259,7 +255,7 @@ class _ButtonBarRow extends Flex {
textBaseline: textBaseline,
);
final double overflowButtonSpacing;
final double? overflowButtonSpacing;
@override
_RenderButtonBarRow createRenderObject(BuildContext context) {
......@@ -268,7 +264,7 @@ class _ButtonBarRow extends Flex {
mainAxisAlignment: mainAxisAlignment,
mainAxisSize: mainAxisSize,
crossAxisAlignment: crossAxisAlignment,
textDirection: getEffectiveTextDirection(context),
textDirection: getEffectiveTextDirection(context)!,
verticalDirection: verticalDirection,
textBaseline: textBaseline,
overflowButtonSpacing: overflowButtonSpacing,
......@@ -307,14 +303,14 @@ class _RenderButtonBarRow extends RenderFlex {
/// Creates a button bar that attempts to display in a row, but displays in
/// a column if there is insufficient horizontal space.
_RenderButtonBarRow({
List<RenderBox> children,
List<RenderBox>? children,
Axis direction = Axis.horizontal,
MainAxisSize mainAxisSize = MainAxisSize.max,
MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start,
CrossAxisAlignment crossAxisAlignment = CrossAxisAlignment.center,
@required TextDirection textDirection,
required TextDirection textDirection,
VerticalDirection verticalDirection = VerticalDirection.down,
TextBaseline textBaseline,
TextBaseline? textBaseline,
this.overflowButtonSpacing,
}) : assert(textDirection != null),
assert(overflowButtonSpacing == null || overflowButtonSpacing >= 0),
......@@ -330,13 +326,13 @@ class _RenderButtonBarRow extends RenderFlex {
);
bool _hasCheckedLayoutWidth = false;
double overflowButtonSpacing;
double? overflowButtonSpacing;
@override
BoxConstraints get constraints {
if (_hasCheckedLayoutWidth)
return super.constraints;
return super.constraints?.copyWith(maxWidth: double.infinity);
return super.constraints.copyWith(maxWidth: double.infinity);
}
@override
......@@ -359,7 +355,7 @@ class _RenderButtonBarRow extends RenderFlex {
super.performLayout();
} else {
final BoxConstraints childConstraints = constraints.copyWith(minWidth: 0.0);
RenderBox child;
RenderBox? child;
double currentHeight = 0.0;
switch (verticalDirection) {
case VerticalDirection.down:
......@@ -381,7 +377,7 @@ class _RenderButtonBarRow extends RenderFlex {
// alignment for a row. For [MainAxisAlignment.spaceAround],
// [MainAxisAlignment.spaceBetween] and [MainAxisAlignment.spaceEvenly]
// cases, use [MainAxisAlignment.start].
switch (textDirection) {
switch (textDirection!) {
case TextDirection.ltr:
switch (mainAxisAlignment) {
case MainAxisAlignment.center:
......@@ -422,7 +418,7 @@ class _RenderButtonBarRow extends RenderFlex {
}
if (overflowButtonSpacing != null && child != null)
currentHeight += overflowButtonSpacing;
currentHeight += overflowButtonSpacing!;
}
size = constraints.constrain(Size(constraints.maxWidth, currentHeight));
}
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:ui' show lerpDouble;
import 'package:flutter/foundation.dart';
......@@ -46,10 +44,10 @@ class ButtonBarThemeData with Diagnosticable {
assert(buttonHeight == null || buttonHeight >= 0.0);
/// How the children should be placed along the horizontal axis.
final MainAxisAlignment alignment;
final MainAxisAlignment? alignment;
/// How much horizontal space is available. See [Row.mainAxisSize].
final MainAxisSize mainAxisSize;
final MainAxisSize? mainAxisSize;
/// Defines a [ButtonBar] button's base colors, and the defaults for
/// the button's minimum size, internal padding, and shape.
......@@ -59,7 +57,7 @@ class ButtonBarThemeData with Diagnosticable {
///
/// Despite the name, this property is not a [TextTheme], its value is not a
/// collection of [TextStyle]s.
final ButtonTextTheme buttonTextTheme;
final ButtonTextTheme? buttonTextTheme;
/// The minimum width for [ButtonBar] buttons.
///
......@@ -68,19 +66,19 @@ class ButtonBarThemeData with Diagnosticable {
///
/// The actual horizontal space allocated for a button's child is
/// at least this value less the theme's horizontal [ButtonThemeData.padding].
final double buttonMinWidth;
final double? buttonMinWidth;
/// The minimum height for [ButtonBar] buttons.
///
/// This will override the surrounding [ButtonThemeData.height] setting
/// for buttons contained in the [ButtonBar].
final double buttonHeight;
final double? buttonHeight;
/// Padding for a [ButtonBar] button's child (typically the button's label).
///
/// This will override the surrounding [ButtonThemeData.padding] setting
/// for buttons contained in the [ButtonBar].
final EdgeInsetsGeometry buttonPadding;
final EdgeInsetsGeometry? buttonPadding;
/// If true, then a [DropdownButton] menu's width will match the [ButtonBar]
/// button's width.
......@@ -95,11 +93,11 @@ class ButtonBarThemeData with Diagnosticable {
///
/// This property only affects [DropdownButton] contained in a [ButtonBar]
/// and its menu.
final bool buttonAlignedDropdown;
final bool? buttonAlignedDropdown;
/// Defines whether a [ButtonBar] should size itself with a minimum size
/// constraint or with padding.
final ButtonBarLayoutBehavior layoutBehavior;
final ButtonBarLayoutBehavior? layoutBehavior;
/// Defines the vertical direction of a [ButtonBar]'s children if it
/// overflows.
......@@ -111,20 +109,20 @@ class ButtonBarThemeData with Diagnosticable {
/// the first action will be at the bottom of the column if this
/// property is set to [VerticalDirection.up], since it "starts" at the
/// bottom and "ends" at the top.
final VerticalDirection overflowDirection;
final VerticalDirection? overflowDirection;
/// Creates a copy of this object but with the given fields replaced with the
/// new values.
ButtonBarThemeData copyWith({
MainAxisAlignment alignment,
MainAxisSize mainAxisSize,
ButtonTextTheme buttonTextTheme,
double buttonMinWidth,
double buttonHeight,
EdgeInsetsGeometry buttonPadding,
bool buttonAlignedDropdown,
ButtonBarLayoutBehavior layoutBehavior,
VerticalDirection overflowDirection,
MainAxisAlignment? alignment,
MainAxisSize? mainAxisSize,
ButtonTextTheme? buttonTextTheme,
double? buttonMinWidth,
double? buttonHeight,
EdgeInsetsGeometry? buttonPadding,
bool? buttonAlignedDropdown,
ButtonBarLayoutBehavior? layoutBehavior,
VerticalDirection? overflowDirection,
}) {
return ButtonBarThemeData(
alignment: alignment ?? this.alignment,
......@@ -144,20 +142,20 @@ class ButtonBarThemeData with Diagnosticable {
/// If both arguments are null, then null is returned.
///
/// {@macro dart.ui.shadow.lerp}
static ButtonBarThemeData lerp(ButtonBarThemeData a, ButtonBarThemeData b, double t) {
static ButtonBarThemeData? lerp(ButtonBarThemeData? a, ButtonBarThemeData? b, double t) {
assert(t != null);
if (a == null && b == null)
return null;
return ButtonBarThemeData(
alignment: t < 0.5 ? a.alignment : b.alignment,
mainAxisSize: t < 0.5 ? a.mainAxisSize : b.mainAxisSize,
buttonTextTheme: t < 0.5 ? a.buttonTextTheme : b.buttonTextTheme,
alignment: t < 0.5 ? a?.alignment : b?.alignment,
mainAxisSize: t < 0.5 ? a?.mainAxisSize : b?.mainAxisSize,
buttonTextTheme: t < 0.5 ? a?.buttonTextTheme : b?.buttonTextTheme,
buttonMinWidth: lerpDouble(a?.buttonMinWidth, b?.buttonMinWidth, t),
buttonHeight: lerpDouble(a?.buttonHeight, b?.buttonHeight, t),
buttonPadding: EdgeInsetsGeometry.lerp(a?.buttonPadding, b?.buttonPadding, t),
buttonAlignedDropdown: t < 0.5 ? a.buttonAlignedDropdown : b.buttonAlignedDropdown,
layoutBehavior: t < 0.5 ? a.layoutBehavior : b.layoutBehavior,
overflowDirection: t < 0.5 ? a.overflowDirection : b.overflowDirection,
buttonAlignedDropdown: t < 0.5 ? a?.buttonAlignedDropdown : b?.buttonAlignedDropdown,
layoutBehavior: t < 0.5 ? a?.layoutBehavior : b?.layoutBehavior,
overflowDirection: t < 0.5 ? a?.overflowDirection : b?.overflowDirection,
);
}
......@@ -235,9 +233,9 @@ class ButtonBarTheme extends InheritedWidget {
///
/// The [data] must not be null.
const ButtonBarTheme({
Key key,
@required this.data,
Widget child,
Key? key,
required this.data,
required Widget child,
}) : assert(data != null), super(key: key, child: child);
/// The properties used for all descendant [ButtonBar] widgets.
......@@ -253,8 +251,8 @@ class ButtonBarTheme extends InheritedWidget {
/// ButtonBarThemeData theme = ButtonBarTheme.of(context);
/// ```
static ButtonBarThemeData of(BuildContext context) {
final ButtonBarTheme buttonBarTheme = context.dependOnInheritedWidgetOfExactType<ButtonBarTheme>();
return buttonBarTheme?.data ?? Theme.of(context).buttonBarTheme;
final ButtonBarTheme? buttonBarTheme = context.dependOnInheritedWidgetOfExactType<ButtonBarTheme>();
return buttonBarTheme?.data ?? Theme.of(context)!.buttonBarTheme;
}
@override
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:ui' show lerpDouble;
import 'package:flutter/foundation.dart';
......@@ -122,10 +120,10 @@ class ButtonStyle with Diagnosticable {
///
/// The color of the [textStyle] is typically not used directly, the
/// [foregroundColor] is used instead.
final MaterialStateProperty<TextStyle> textStyle;
final MaterialStateProperty<TextStyle>? textStyle;
/// The button's background fill color.
final MaterialStateProperty<Color> backgroundColor;
final MaterialStateProperty<Color>? backgroundColor;
/// The color for the button's [Text] and [Icon] widget descendants.
///
......@@ -133,11 +131,11 @@ class ButtonStyle with Diagnosticable {
/// of the components that compute defaults from [ButtonStyle] values
/// compute a default [foregroundColor] and use that instead of the
/// [textStyle]'s color.
final MaterialStateProperty<Color> foregroundColor;
final MaterialStateProperty<Color>? foregroundColor;
/// The highlight color that's typically used to indicate that
/// the button is focused, hovered, or pressed.
final MaterialStateProperty<Color> overlayColor;
final MaterialStateProperty<Color>? overlayColor;
/// The shadow color of the button's [Material].
///
......@@ -145,35 +143,35 @@ class ButtonStyle with Diagnosticable {
/// dark themes, so by default the button classes add a
/// semi-transparent overlay to indicate elevation. See
/// [ThemeData.applyElevationOverlayColor].
final MaterialStateProperty<Color> shadowColor;
final MaterialStateProperty<Color>? shadowColor;
/// The elevation of the button's [Material].
final MaterialStateProperty<double> elevation;
final MaterialStateProperty<double>? elevation;
/// The padding between the button's boundary and its child.
final MaterialStateProperty<EdgeInsetsGeometry> padding;
final MaterialStateProperty<EdgeInsetsGeometry>? padding;
/// The minimum size of the button itself.
///
/// The size of the rectangle the button lies within may be larger
/// per [tapTargetSize].
final MaterialStateProperty<Size> minimumSize;
final MaterialStateProperty<Size>? minimumSize;
/// The color and weight of the button's outline.
///
/// This value is combined with [shape] to create a shape decorated
/// with an outline.
final MaterialStateProperty<BorderSide> side;
final MaterialStateProperty<BorderSide>? side;
/// The shape of the button's underlying [Material].
///
/// This shape is combined with [side] to create a shape decorated
/// with an outline.
final MaterialStateProperty<OutlinedBorder> shape;
final MaterialStateProperty<OutlinedBorder>? shape;
/// The cursor for a mouse pointer when it enters or is hovering over
/// this button's [InkWell].
final MaterialStateProperty<MouseCursor> mouseCursor;
final MaterialStateProperty<MouseCursor>? mouseCursor;
/// Defines how compact the button's layout will be.
///
......@@ -183,7 +181,7 @@ class ButtonStyle with Diagnosticable {
///
/// * [ThemeData.visualDensity], which specifies the [visualDensity] for all widgets
/// within a [Theme].
final VisualDensity visualDensity;
final VisualDensity? visualDensity;
/// Configures the minimum size of the area within which the button may be pressed.
///
......@@ -191,12 +189,12 @@ class ButtonStyle with Diagnosticable {
/// a transparent margin that responds to taps.
///
/// Always defaults to [ThemeData.materialTapTargetSize].
final MaterialTapTargetSize tapTargetSize;
final MaterialTapTargetSize? tapTargetSize;
/// Defines the duration of animated changes for [shape] and [elevation].
///
/// Typically the component default value is [kThemeChangeDuration].
final Duration animationDuration;
final Duration? animationDuration;
/// Whether detected gestures should provide acoustic and/or haptic feedback.
///
......@@ -208,26 +206,26 @@ class ButtonStyle with Diagnosticable {
/// See also:
///
/// * [Feedback] for providing platform-specific feedback to certain actions.
final bool enableFeedback;
final bool? enableFeedback;
/// Returns a copy of this ButtonStyle with the given fields replaced with
/// the new values.
ButtonStyle copyWith({
MaterialStateProperty<TextStyle> textStyle,
MaterialStateProperty<Color> backgroundColor,
MaterialStateProperty<Color> foregroundColor,
MaterialStateProperty<Color> overlayColor,
MaterialStateProperty<Color> shadowColor,
MaterialStateProperty<double> elevation,
MaterialStateProperty<EdgeInsetsGeometry> padding,
MaterialStateProperty<Size> minimumSize,
MaterialStateProperty<BorderSide> side,
MaterialStateProperty<OutlinedBorder> shape,
MaterialStateProperty<MouseCursor> mouseCursor,
VisualDensity visualDensity,
MaterialTapTargetSize tapTargetSize,
Duration animationDuration,
bool enableFeedback,
MaterialStateProperty<TextStyle>? textStyle,
MaterialStateProperty<Color>? backgroundColor,
MaterialStateProperty<Color>? foregroundColor,
MaterialStateProperty<Color>? overlayColor,
MaterialStateProperty<Color>? shadowColor,
MaterialStateProperty<double>? elevation,
MaterialStateProperty<EdgeInsetsGeometry>? padding,
MaterialStateProperty<Size>? minimumSize,
MaterialStateProperty<BorderSide>? side,
MaterialStateProperty<OutlinedBorder>? shape,
MaterialStateProperty<MouseCursor>? mouseCursor,
VisualDensity? visualDensity,
MaterialTapTargetSize? tapTargetSize,
Duration? animationDuration,
bool? enableFeedback,
}) {
return ButtonStyle(
textStyle: textStyle ?? this.textStyle,
......@@ -253,7 +251,7 @@ class ButtonStyle with Diagnosticable {
///
/// In other words, [style] is used to fill in unspecified (null) fields
/// this ButtonStyle.
ButtonStyle merge(ButtonStyle style) {
ButtonStyle merge(ButtonStyle? style) {
if (style == null)
return this;
return copyWith(
......@@ -341,7 +339,7 @@ class ButtonStyle with Diagnosticable {
}
/// Linearly interpolate between two [ButtonStyle]s.
static ButtonStyle lerp(ButtonStyle a, ButtonStyle b, double t) {
static ButtonStyle? lerp(ButtonStyle? a, ButtonStyle? b, double t) {
assert (t != null);
if (a == null && b == null)
return null;
......@@ -356,15 +354,15 @@ class ButtonStyle with Diagnosticable {
minimumSize: _lerpProperties<Size>(a?.minimumSize, b?.minimumSize, t, Size.lerp),
side: _lerpSides(a?.side, b?.side, t),
shape: _lerpShapes(a?.shape, b?.shape, t),
mouseCursor: t < 0.5 ? a.mouseCursor : b.mouseCursor,
visualDensity: t < 0.5 ? a.visualDensity : b.visualDensity,
tapTargetSize: t < 0.5 ? a.tapTargetSize : b.tapTargetSize,
animationDuration: t < 0.5 ? a.animationDuration : b.animationDuration,
enableFeedback: t < 0.5 ? a.enableFeedback : b.enableFeedback,
mouseCursor: t < 0.5 ? a?.mouseCursor : b?.mouseCursor,
visualDensity: t < 0.5 ? a?.visualDensity : b?.visualDensity,
tapTargetSize: t < 0.5 ? a?.tapTargetSize : b?.tapTargetSize,
animationDuration: t < 0.5 ? a?.animationDuration : b?.animationDuration,
enableFeedback: t < 0.5 ? a?.enableFeedback : b?.enableFeedback,
);
}
static MaterialStateProperty<T> _lerpProperties<T>(MaterialStateProperty<T> a, MaterialStateProperty<T> b, double t, T Function(T, T, double) lerpFunction ) {
static MaterialStateProperty<T>? _lerpProperties<T>(MaterialStateProperty<T>? a, MaterialStateProperty<T>? b, double t, T? Function(T?, T?, double) lerpFunction ) {
// Avoid creating a _LerpProperties object for a common case.
if (a == null && b == null)
return null;
......@@ -372,14 +370,14 @@ class ButtonStyle with Diagnosticable {
}
// Special case because BorderSide.lerp() doesn't support null arguments
static MaterialStateProperty<BorderSide> _lerpSides(MaterialStateProperty<BorderSide> a, MaterialStateProperty<BorderSide> b, double t) {
static MaterialStateProperty<BorderSide>? _lerpSides(MaterialStateProperty<BorderSide>? a, MaterialStateProperty<BorderSide>? b, double t) {
if (a == null && b == null)
return null;
return _LerpSides(a, b, t);
}
// TODO(hansmuller): OutlinedBorder needs a lerp method - https://github.com/flutter/flutter/issues/60555.
static MaterialStateProperty<OutlinedBorder> _lerpShapes(MaterialStateProperty<OutlinedBorder> a, MaterialStateProperty<OutlinedBorder> b, double t) {
static MaterialStateProperty<OutlinedBorder>? _lerpShapes(MaterialStateProperty<OutlinedBorder>? a, MaterialStateProperty<OutlinedBorder>? b, double t) {
if (a == null && b == null)
return null;
return _LerpShapes(a, b, t);
......@@ -389,15 +387,15 @@ class ButtonStyle with Diagnosticable {
class _LerpProperties<T> implements MaterialStateProperty<T> {
const _LerpProperties(this.a, this.b, this.t, this.lerpFunction);
final MaterialStateProperty<T> a;
final MaterialStateProperty<T> b;
final MaterialStateProperty<T>? a;
final MaterialStateProperty<T>? b;
final double t;
final T Function(T, T, double) lerpFunction;
final T? Function(T?, T?, double) lerpFunction;
@override
T resolve(Set<MaterialState> states) {
final T resolvedA = a?.resolve(states);
final T resolvedB = b?.resolve(states);
T? resolve(Set<MaterialState> states) {
final T? resolvedA = a?.resolve(states);
final T? resolvedB = b?.resolve(states);
return lerpFunction(resolvedA, resolvedB, t);
}
}
......@@ -405,18 +403,18 @@ class _LerpProperties<T> implements MaterialStateProperty<T> {
class _LerpSides implements MaterialStateProperty<BorderSide> {
const _LerpSides(this.a, this.b, this.t);
final MaterialStateProperty<BorderSide> a;
final MaterialStateProperty<BorderSide> b;
final MaterialStateProperty<BorderSide>? a;
final MaterialStateProperty<BorderSide>? b;
final double t;
@override
BorderSide resolve(Set<MaterialState> states) {
final BorderSide resolvedA = a?.resolve(states);
final BorderSide resolvedB = b?.resolve(states);
BorderSide? resolve(Set<MaterialState> states) {
final BorderSide? resolvedA = a?.resolve(states);
final BorderSide? resolvedB = b?.resolve(states);
if (resolvedA == null && resolvedB == null)
return null;
if (resolvedA == null)
return BorderSide.lerp(BorderSide(width: 0, color: resolvedB.color.withAlpha(0)), resolvedB, t);
return BorderSide.lerp(BorderSide(width: 0, color: resolvedB!.color.withAlpha(0)), resolvedB, t);
if (resolvedB == null)
return BorderSide.lerp(BorderSide(width: 0, color: resolvedA.color.withAlpha(0)), resolvedA, t);
return BorderSide.lerp(resolvedA, resolvedB, t);
......@@ -426,14 +424,14 @@ class _LerpSides implements MaterialStateProperty<BorderSide> {
class _LerpShapes implements MaterialStateProperty<OutlinedBorder> {
const _LerpShapes(this.a, this.b, this.t);
final MaterialStateProperty<OutlinedBorder> a;
final MaterialStateProperty<OutlinedBorder> b;
final MaterialStateProperty<OutlinedBorder>? a;
final MaterialStateProperty<OutlinedBorder>? b;
final double t;
@override
OutlinedBorder resolve(Set<MaterialState> states) {
final OutlinedBorder resolvedA = a?.resolve(states);
final OutlinedBorder resolvedB = b?.resolve(states);
return ShapeBorder.lerp(resolvedA, resolvedB, t) as OutlinedBorder;
OutlinedBorder? resolve(Set<MaterialState> states) {
final OutlinedBorder? resolvedA = a?.resolve(states);
final OutlinedBorder? resolvedB = b?.resolve(states);
return ShapeBorder.lerp(resolvedA, resolvedB, t) as OutlinedBorder?;
}
}
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:math' as math;
import 'package:flutter/foundation.dart';
......@@ -32,14 +30,14 @@ import 'theme_data.dart';
abstract class ButtonStyleButton extends StatefulWidget {
/// Create a [ButtonStyleButton].
const ButtonStyleButton({
Key key,
@required this.onPressed,
@required this.onLongPress,
@required this.style,
@required this.focusNode,
@required this.autofocus,
@required this.clipBehavior,
@required this.child,
Key? key,
required this.onPressed,
required this.onLongPress,
required this.style,
required this.focusNode,
required this.autofocus,
required this.clipBehavior,
required this.child,
}) : assert(autofocus != null),
assert(clipBehavior != null),
super(key: key);
......@@ -51,7 +49,7 @@ abstract class ButtonStyleButton extends StatefulWidget {
/// See also:
///
/// * [enabled], which is true if the button is enabled.
final VoidCallback onPressed;
final VoidCallback? onPressed;
/// Called when the button is long-pressed.
///
......@@ -60,7 +58,7 @@ abstract class ButtonStyleButton extends StatefulWidget {
/// See also:
///
/// * [enabled], which is true if the button is enabled.
final VoidCallback onLongPress;
final VoidCallback? onLongPress;
/// Customizes this button's appearance.
///
......@@ -70,7 +68,7 @@ abstract class ButtonStyleButton extends StatefulWidget {
/// [MaterialStateProperty]s in [themeStyleOf] and [defaultStyleOf].
///
/// Null by default.
final ButtonStyle style;
final ButtonStyle? style;
/// {@macro flutter.widgets.Clip}
///
......@@ -78,13 +76,13 @@ abstract class ButtonStyleButton extends StatefulWidget {
final Clip clipBehavior;
/// {@macro flutter.widgets.Focus.focusNode}
final FocusNode focusNode;
final FocusNode? focusNode;
/// {@macro flutter.widgets.Focus.autofocus}
final bool autofocus;
/// Typically the button's label.
final Widget child;
final Widget? child;
/// Returns a non-null [ButtonStyle] that's based primarily on the [Theme]'s
/// [ThemeData.textTheme] and [ThemeData.colorScheme].
......@@ -117,7 +115,7 @@ abstract class ButtonStyleButton extends StatefulWidget {
///
/// * [defaultStyleOf], Returns the default [ButtonStyle] for this button.
@protected
ButtonStyle themeStyleOf(BuildContext context);
ButtonStyle? themeStyleOf(BuildContext context);
/// Whether the button is enabled or disabled.
///
......@@ -139,7 +137,7 @@ abstract class ButtonStyleButton extends StatefulWidget {
/// Returns null if [value] is null, otherwise `MaterialStateProperty.all<T>(value)`.
///
/// A convenience method for subclasses.
static MaterialStateProperty<T> allOrNull<T>(T value) => value == null ? null : MaterialStateProperty.all<T>(value);
static MaterialStateProperty<T>? allOrNull<T>(T? value) => value == null ? null : MaterialStateProperty.all<T>(value);
/// Returns an interpolated value based on the [textScaleFactor] parameter:
///
......@@ -165,9 +163,9 @@ abstract class ButtonStyleButton extends StatefulWidget {
} else if (textScaleFactor >= 3) {
return geometry3x;
} else if (textScaleFactor <= 2) {
return EdgeInsetsGeometry.lerp(geometry1x, geometry2x, textScaleFactor - 1);
return EdgeInsetsGeometry.lerp(geometry1x, geometry2x, textScaleFactor - 1)!;
}
return EdgeInsetsGeometry.lerp(geometry2x, geometry3x, textScaleFactor - 2);
return EdgeInsetsGeometry.lerp(geometry2x, geometry3x, textScaleFactor - 2)!;
}
}
......@@ -180,9 +178,9 @@ abstract class ButtonStyleButton extends StatefulWidget {
/// * [ElevatedButton], a filled button whose material elevates when pressed.
/// * [OutlinedButton], similar to [TextButton], but with an outline.
class _ButtonStyleState extends State<ButtonStyleButton> with TickerProviderStateMixin {
AnimationController _controller;
double _elevation;
Color _backgroundColor;
AnimationController? _controller;
double? _elevation;
Color? _backgroundColor;
final Set<MaterialState> _states = <MaterialState>{};
bool get _hovered => _states.contains(MaterialState.hovered);
......@@ -245,54 +243,54 @@ class _ButtonStyleState extends State<ButtonStyleButton> with TickerProviderStat
@override
Widget build(BuildContext context) {
final ButtonStyle widgetStyle = widget.style;
final ButtonStyle themeStyle = widget.themeStyleOf(context);
final ButtonStyle? widgetStyle = widget.style;
final ButtonStyle? themeStyle = widget.themeStyleOf(context);
final ButtonStyle defaultStyle = widget.defaultStyleOf(context);
assert(defaultStyle != null);
T effectiveValue<T>(T Function(ButtonStyle style) getProperty) {
final T widgetValue = getProperty(widgetStyle);
final T themeValue = getProperty(themeStyle);
final T defaultValue = getProperty(defaultStyle);
T? effectiveValue<T>(T? Function(ButtonStyle? style) getProperty) {
final T? widgetValue = getProperty(widgetStyle);
final T? themeValue = getProperty(themeStyle);
final T? defaultValue = getProperty(defaultStyle);
return widgetValue ?? themeValue ?? defaultValue;
}
T resolve<T>(MaterialStateProperty<T> Function(ButtonStyle style) getProperty) {
T? resolve<T>(MaterialStateProperty<T>? Function(ButtonStyle? style) getProperty) {
return effectiveValue(
(ButtonStyle style) => getProperty(style)?.resolve(_states),
(ButtonStyle? style) => getProperty(style)?.resolve(_states),
);
}
final double resolvedElevation = resolve<double>((ButtonStyle style) => style?.elevation);
final TextStyle resolvedTextStyle = resolve<TextStyle>((ButtonStyle style) => style?.textStyle);
Color resolvedBackgroundColor = resolve<Color>((ButtonStyle style) => style?.backgroundColor);
final Color resolvedForegroundColor = resolve<Color>((ButtonStyle style) => style?.foregroundColor);
final Color resolvedShadowColor = resolve<Color>((ButtonStyle style) => style?.shadowColor);
final EdgeInsetsGeometry resolvedPadding = resolve<EdgeInsetsGeometry>((ButtonStyle style) => style?.padding);
final Size resolvedMinimumSize = resolve<Size>((ButtonStyle style) => style?.minimumSize);
final BorderSide resolvedSide = resolve<BorderSide>((ButtonStyle style) => style?.side);
final OutlinedBorder resolvedShape = resolve<OutlinedBorder>((ButtonStyle style) => style?.shape);
final double? resolvedElevation = resolve<double>((ButtonStyle? style) => style?.elevation);
final TextStyle? resolvedTextStyle = resolve<TextStyle>((ButtonStyle? style) => style?.textStyle);
Color? resolvedBackgroundColor = resolve<Color>((ButtonStyle? style) => style?.backgroundColor);
final Color? resolvedForegroundColor = resolve<Color>((ButtonStyle? style) => style?.foregroundColor);
final Color? resolvedShadowColor = resolve<Color>((ButtonStyle? style) => style?.shadowColor);
final EdgeInsetsGeometry? resolvedPadding = resolve<EdgeInsetsGeometry>((ButtonStyle? style) => style?.padding);
final Size? resolvedMinimumSize = resolve<Size>((ButtonStyle? style) => style?.minimumSize);
final BorderSide? resolvedSide = resolve<BorderSide>((ButtonStyle? style) => style?.side);
final OutlinedBorder? resolvedShape = resolve<OutlinedBorder>((ButtonStyle? style) => style?.shape);
final MaterialStateMouseCursor resolvedMouseCursor = _MouseCursor(
(Set<MaterialState> states) => effectiveValue((ButtonStyle style) => style?.mouseCursor?.resolve(states)),
(Set<MaterialState> states) => effectiveValue((ButtonStyle? style) => style?.mouseCursor?.resolve(states)),
);
final MaterialStateProperty<Color> overlayColor = MaterialStateProperty.resolveWith<Color>(
(Set<MaterialState> states) => effectiveValue((ButtonStyle style) => style?.overlayColor?.resolve(states)),
(Set<MaterialState> states) => effectiveValue((ButtonStyle? style) => style?.overlayColor?.resolve(states)),
);
final VisualDensity resolvedVisualDensity = effectiveValue((ButtonStyle style) => style?.visualDensity);
final MaterialTapTargetSize resolvedTapTargetSize = effectiveValue((ButtonStyle style) => style?.tapTargetSize);
final Duration resolvedAnimationDuration = effectiveValue((ButtonStyle style) => style?.animationDuration);
final bool resolvedEnableFeedback = effectiveValue((ButtonStyle style) => style?.enableFeedback);
final Offset densityAdjustment = resolvedVisualDensity.baseSizeAdjustment;
final VisualDensity? resolvedVisualDensity = effectiveValue((ButtonStyle? style) => style?.visualDensity);
final MaterialTapTargetSize? resolvedTapTargetSize = effectiveValue((ButtonStyle? style) => style?.tapTargetSize);
final Duration? resolvedAnimationDuration = effectiveValue((ButtonStyle? style) => style?.animationDuration);
final bool? resolvedEnableFeedback = effectiveValue((ButtonStyle? style) => style?.enableFeedback);
final Offset densityAdjustment = resolvedVisualDensity!.baseSizeAdjustment;
final BoxConstraints effectiveConstraints = resolvedVisualDensity.effectiveConstraints(
BoxConstraints(
minWidth: resolvedMinimumSize.width,
minWidth: resolvedMinimumSize!.width,
minHeight: resolvedMinimumSize.height,
),
);
final EdgeInsetsGeometry padding = resolvedPadding.add(
final EdgeInsetsGeometry padding = resolvedPadding!.add(
EdgeInsets.only(
left: densityAdjustment.dx,
top: densityAdjustment.dy,
......@@ -305,12 +303,12 @@ class _ButtonStyleState extends State<ButtonStyleButton> with TickerProviderStat
// elevation is changing, change the elevation first. Material implicitly
// animates its elevation but not its color. SKIA renders non-zero
// elevations as a shadow colored fill behind the Material's background.
if (resolvedAnimationDuration > Duration.zero
if (resolvedAnimationDuration! > Duration.zero
&& _elevation != null
&& _backgroundColor != null
&& _elevation != resolvedElevation
&& _backgroundColor.value != resolvedBackgroundColor.value
&& _backgroundColor.opacity == 1
&& _backgroundColor!.value != resolvedBackgroundColor!.value
&& _backgroundColor!.opacity == 1
&& resolvedBackgroundColor.opacity < 1
&& resolvedElevation == 0) {
if (_controller?.duration != resolvedAnimationDuration) {
......@@ -326,8 +324,8 @@ class _ButtonStyleState extends State<ButtonStyleButton> with TickerProviderStat
});
}
resolvedBackgroundColor = _backgroundColor; // Defer changing the background color.
_controller.value = 0;
_controller.forward();
_controller!.value = 0;
_controller!.forward();
}
_elevation = resolvedElevation;
_backgroundColor = resolvedBackgroundColor;
......@@ -335,9 +333,9 @@ class _ButtonStyleState extends State<ButtonStyleButton> with TickerProviderStat
final Widget result = ConstrainedBox(
constraints: effectiveConstraints,
child: Material(
elevation: resolvedElevation,
elevation: resolvedElevation!,
textStyle: resolvedTextStyle?.copyWith(color: resolvedForegroundColor),
shape: resolvedShape.copyWith(side: resolvedSide),
shape: resolvedShape!.copyWith(side: resolvedSide),
color: resolvedBackgroundColor,
shadowColor: resolvedShadowColor,
type: resolvedBackgroundColor == null ? MaterialType.transparency : MaterialType.button,
......@@ -374,7 +372,7 @@ class _ButtonStyleState extends State<ButtonStyleButton> with TickerProviderStat
);
Size minSize;
switch (resolvedTapTargetSize) {
switch (resolvedTapTargetSize!) {
case MaterialTapTargetSize.padded:
minSize = Size(
kMinInteractiveDimension + densityAdjustment.dx,
......@@ -406,7 +404,7 @@ class _MouseCursor extends MaterialStateMouseCursor {
final MaterialPropertyResolver<MouseCursor> resolveCallback;
@override
MouseCursor resolve(Set<MaterialState> states) => resolveCallback(states);
MouseCursor? resolve(Set<MaterialState> states) => resolveCallback(states);
@override
String get debugDescription => 'ButtonStyleButton_MouseCursor';
......@@ -419,9 +417,9 @@ class _MouseCursor extends MaterialStateMouseCursor {
/// "tap target", but not its material or its ink splashes.
class _InputPadding extends SingleChildRenderObjectWidget {
const _InputPadding({
Key key,
Widget child,
this.minSize,
Key? key,
Widget? child,
required this.minSize,
}) : super(key: key, child: child);
final Size minSize;
......@@ -438,7 +436,7 @@ class _InputPadding extends SingleChildRenderObjectWidget {
}
class _RenderInputPadding extends RenderShiftedBox {
_RenderInputPadding(this._minSize, [RenderBox child]) : super(child);
_RenderInputPadding(this._minSize, [RenderBox? child]) : super(child);
Size get minSize => _minSize;
Size _minSize;
......@@ -452,28 +450,28 @@ class _RenderInputPadding extends RenderShiftedBox {
@override
double computeMinIntrinsicWidth(double height) {
if (child != null)
return math.max(child.getMinIntrinsicWidth(height), minSize.width);
return math.max(child!.getMinIntrinsicWidth(height), minSize.width);
return 0.0;
}
@override
double computeMinIntrinsicHeight(double width) {
if (child != null)
return math.max(child.getMinIntrinsicHeight(width), minSize.height);
return math.max(child!.getMinIntrinsicHeight(width), minSize.height);
return 0.0;
}
@override
double computeMaxIntrinsicWidth(double height) {
if (child != null)
return math.max(child.getMaxIntrinsicWidth(height), minSize.width);
return math.max(child!.getMaxIntrinsicWidth(height), minSize.width);
return 0.0;
}
@override
double computeMaxIntrinsicHeight(double width) {
if (child != null)
return math.max(child.getMaxIntrinsicHeight(width), minSize.height);
return math.max(child!.getMaxIntrinsicHeight(width), minSize.height);
return 0.0;
}
......@@ -481,29 +479,29 @@ class _RenderInputPadding extends RenderShiftedBox {
void performLayout() {
final BoxConstraints constraints = this.constraints;
if (child != null) {
child.layout(constraints, parentUsesSize: true);
final double height = math.max(child.size.width, minSize.width);
final double width = math.max(child.size.height, minSize.height);
child!.layout(constraints, parentUsesSize: true);
final double height = math.max(child!.size.width, minSize.width);
final double width = math.max(child!.size.height, minSize.height);
size = constraints.constrain(Size(height, width));
final BoxParentData childParentData = child.parentData as BoxParentData;
childParentData.offset = Alignment.center.alongOffset(size - child.size as Offset);
final BoxParentData childParentData = child!.parentData as BoxParentData;
childParentData.offset = Alignment.center.alongOffset(size - child!.size as Offset);
} else {
size = Size.zero;
}
}
@override
bool hitTest(BoxHitTestResult result, { Offset position }) {
bool hitTest(BoxHitTestResult result, { required Offset position }) {
if (super.hitTest(result, position: position)) {
return true;
}
final Offset center = child.size.center(Offset.zero);
final Offset center = child!.size.center(Offset.zero);
return result.addWithRawTransform(
transform: MatrixUtils.forceToPoint(center),
position: center,
hitTest: (BoxHitTestResult result, Offset position) {
hitTest: (BoxHitTestResult result, Offset? position) {
assert(position == center);
return child.hitTest(result, position: center);
return child!.hitTest(result, position: center);
},
);
}
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
......@@ -81,23 +79,23 @@ class ButtonTheme extends InheritedTheme {
/// The [textTheme], [minWidth], [height], and [colorScheme] arguments
/// must not be null.
ButtonTheme({
Key key,
Key? key,
ButtonTextTheme textTheme = ButtonTextTheme.normal,
ButtonBarLayoutBehavior layoutBehavior = ButtonBarLayoutBehavior.padded,
double minWidth = 88.0,
double height = 36.0,
EdgeInsetsGeometry padding,
ShapeBorder shape,
EdgeInsetsGeometry? padding,
ShapeBorder? shape,
bool alignedDropdown = false,
Color buttonColor,
Color disabledColor,
Color focusColor,
Color hoverColor,
Color highlightColor,
Color splashColor,
ColorScheme colorScheme,
MaterialTapTargetSize materialTapTargetSize,
Widget child,
Color? buttonColor,
Color? disabledColor,
Color? focusColor,
Color? hoverColor,
Color? highlightColor,
Color? splashColor,
ColorScheme? colorScheme,
MaterialTapTargetSize? materialTapTargetSize,
required Widget child,
}) : assert(textTheme != null),
assert(minWidth != null && minWidth >= 0.0),
assert(height != null && height >= 0.0),
......@@ -126,9 +124,9 @@ class ButtonTheme extends InheritedTheme {
///
/// The [data] argument must not be null.
const ButtonTheme.fromButtonThemeData({
Key key,
@required this.data,
Widget child,
Key? key,
required this.data,
required Widget child,
}) : assert(data != null),
super(key: key, child: child);
......@@ -177,21 +175,21 @@ class ButtonTheme extends InheritedTheme {
'This feature was deprecated after v1.9.1.'
)
ButtonTheme.bar({
Key key,
Key? key,
ButtonTextTheme textTheme = ButtonTextTheme.accent,
double minWidth = 64.0,
double height = 36.0,
EdgeInsetsGeometry padding = const EdgeInsets.symmetric(horizontal: 8.0),
ShapeBorder shape,
ShapeBorder? shape,
bool alignedDropdown = false,
Color buttonColor,
Color disabledColor,
Color focusColor,
Color hoverColor,
Color highlightColor,
Color splashColor,
ColorScheme colorScheme,
Widget child,
Color? buttonColor,
Color? disabledColor,
Color? focusColor,
Color? hoverColor,
Color? highlightColor,
Color? splashColor,
ColorScheme? colorScheme,
required Widget child,
ButtonBarLayoutBehavior layoutBehavior = ButtonBarLayoutBehavior.padded,
}) : assert(textTheme != null),
assert(minWidth != null && minWidth >= 0.0),
......@@ -226,10 +224,10 @@ class ButtonTheme extends InheritedTheme {
/// ButtonThemeData theme = ButtonTheme.of(context);
/// ```
static ButtonThemeData of(BuildContext context) {
final ButtonTheme inheritedButtonTheme = context.dependOnInheritedWidgetOfExactType<ButtonTheme>();
ButtonThemeData buttonTheme = inheritedButtonTheme?.data;
final ButtonTheme? inheritedButtonTheme = context.dependOnInheritedWidgetOfExactType<ButtonTheme>();
ButtonThemeData? buttonTheme = inheritedButtonTheme?.data;
if (buttonTheme?.colorScheme == null) { // if buttonTheme or buttonTheme.colorScheme is null
final ThemeData theme = Theme.of(context);
final ThemeData theme = Theme.of(context)!;
buttonTheme ??= theme.buttonTheme;
if (buttonTheme.colorScheme == null) {
buttonTheme = buttonTheme.copyWith(
......@@ -238,12 +236,12 @@ class ButtonTheme extends InheritedTheme {
assert(buttonTheme.colorScheme != null);
}
}
return buttonTheme;
return buttonTheme!;
}
@override
Widget wrap(BuildContext context, Widget child) {
final ButtonTheme ancestorTheme = context.findAncestorWidgetOfExactType<ButtonTheme>();
final ButtonTheme? ancestorTheme = context.findAncestorWidgetOfExactType<ButtonTheme>();
return identical(this, ancestorTheme) ? child : ButtonTheme.fromButtonThemeData(data: data, child: child);
}
......@@ -289,18 +287,18 @@ class ButtonThemeData with Diagnosticable {
this.textTheme = ButtonTextTheme.normal,
this.minWidth = 88.0,
this.height = 36.0,
EdgeInsetsGeometry padding,
ShapeBorder shape,
EdgeInsetsGeometry? padding,
ShapeBorder? shape,
this.layoutBehavior = ButtonBarLayoutBehavior.padded,
this.alignedDropdown = false,
Color buttonColor,
Color disabledColor,
Color focusColor,
Color hoverColor,
Color highlightColor,
Color splashColor,
Color? buttonColor,
Color? disabledColor,
Color? focusColor,
Color? hoverColor,
Color? highlightColor,
Color? splashColor,
this.colorScheme,
MaterialTapTargetSize materialTapTargetSize,
MaterialTapTargetSize? materialTapTargetSize,
}) : assert(textTheme != null),
assert(minWidth != null && minWidth >= 0.0),
assert(height != null && height >= 0.0),
......@@ -369,7 +367,7 @@ class ButtonThemeData with Diagnosticable {
/// and [FlatButton].
EdgeInsetsGeometry get padding {
if (_padding != null)
return _padding;
return _padding!;
switch (textTheme) {
case ButtonTextTheme.normal:
case ButtonTextTheme.accent:
......@@ -377,10 +375,8 @@ class ButtonThemeData with Diagnosticable {
case ButtonTextTheme.primary:
return const EdgeInsets.symmetric(horizontal: 24.0);
}
assert(false);
return EdgeInsets.zero;
}
final EdgeInsetsGeometry _padding;
final EdgeInsetsGeometry? _padding;
/// The shape of a button's material.
///
......@@ -398,7 +394,7 @@ class ButtonThemeData with Diagnosticable {
/// and [FlatButton].
ShapeBorder get shape {
if (_shape != null)
return _shape;
return _shape!;
switch (textTheme) {
case ButtonTextTheme.normal:
case ButtonTextTheme.accent:
......@@ -410,9 +406,8 @@ class ButtonThemeData with Diagnosticable {
borderRadius: BorderRadius.all(Radius.circular(4.0)),
);
}
return const RoundedRectangleBorder();
}
final ShapeBorder _shape;
final ShapeBorder? _shape;
/// If true, then a [DropdownButton] menu's width will match the button's
/// width.
......@@ -437,7 +432,7 @@ class ButtonThemeData with Diagnosticable {
///
/// * [getFillColor], which is used by [RaisedButton] to compute its
/// background fill color.
final Color _buttonColor;
final Color? _buttonColor;
/// The background fill color for disabled [RaisedButton]s.
///
......@@ -447,7 +442,7 @@ class ButtonThemeData with Diagnosticable {
///
/// * [getDisabledFillColor], which is used by [RaisedButton] to compute its
/// background fill color.
final Color _disabledColor;
final Color? _disabledColor;
/// The fill color of the button when it has the input focus.
///
......@@ -460,7 +455,7 @@ class ButtonThemeData with Diagnosticable {
///
/// * [getFocusColor], which is used by [RaisedButton], [OutlineButton]
/// and [FlatButton].
final Color _focusColor;
final Color? _focusColor;
/// The fill color of the button when a pointer is hovering over it.
///
......@@ -473,7 +468,7 @@ class ButtonThemeData with Diagnosticable {
///
/// * [getHoverColor], which is used by [RaisedButton], [OutlineButton]
/// and [FlatButton].
final Color _hoverColor;
final Color? _hoverColor;
/// The color of the overlay that appears when a button is pressed.
///
......@@ -483,7 +478,7 @@ class ButtonThemeData with Diagnosticable {
///
/// * [getHighlightColor], which is used by [RaisedButton], [OutlineButton]
/// and [FlatButton].
final Color _highlightColor;
final Color? _highlightColor;
/// The color of the ink "splash" overlay that appears when a button is tapped.
///
......@@ -493,7 +488,7 @@ class ButtonThemeData with Diagnosticable {
///
/// * [getSplashColor], which is used by [RaisedButton], [OutlineButton]
/// and [FlatButton].
final Color _splashColor;
final Color? _splashColor;
/// A set of thirteen colors that can be used to derive the button theme's
/// colors.
......@@ -505,7 +500,7 @@ class ButtonThemeData with Diagnosticable {
/// The colors for new button classes can be defined exclusively in terms
/// of [colorScheme]. When it's possible, the existing buttons will
/// (continue to) gradually migrate to it.
final ColorScheme colorScheme;
final ColorScheme? colorScheme;
// The minimum size of a button's tap target.
//
......@@ -515,14 +510,14 @@ class ButtonThemeData with Diagnosticable {
//
// * [getMaterialTargetTapSize], which is used by [RaisedButton],
// [OutlineButton] and [FlatButton].
final MaterialTapTargetSize _materialTapTargetSize;
final MaterialTapTargetSize? _materialTapTargetSize;
/// The [button]'s overall brightness.
///
/// Returns the button's [MaterialButton.colorBrightness] if it is non-null,
/// otherwise the color scheme's [ColorScheme.brightness] is returned.
Brightness getBrightness(MaterialButton button) {
return button.colorBrightness ?? colorScheme.brightness;
return button.colorBrightness ?? colorScheme!.brightness;
}
/// Defines the [button]'s base colors, and the defaults for the button's
......@@ -545,10 +540,10 @@ class ButtonThemeData with Diagnosticable {
/// used as the `disabledTextColor`. It will be resolved in the [MaterialState.disabled] state.
Color getDisabledTextColor(MaterialButton button) {
if (button.textColor is MaterialStateProperty<Color>)
return button.textColor;
return button.textColor!;
if (button.disabledTextColor != null)
return button.disabledTextColor;
return colorScheme.onSurface.withOpacity(0.38);
return button.disabledTextColor!;
return colorScheme!.onSurface.withOpacity(0.38);
}
/// The [button]'s background color when [MaterialButton.onPressed] is null
......@@ -563,10 +558,10 @@ class ButtonThemeData with Diagnosticable {
/// with its opacity set to 0.38.
Color getDisabledFillColor(MaterialButton button) {
if (button.disabledColor != null)
return button.disabledColor;
return button.disabledColor!;
if (_disabledColor != null)
return _disabledColor;
return colorScheme.onSurface.withOpacity(0.38);
return _disabledColor!;
return colorScheme!.onSurface.withOpacity(0.38);
}
/// The button's background fill color or null for buttons that don't have
......@@ -594,8 +589,8 @@ class ButtonThemeData with Diagnosticable {
/// otherwise the color scheme's ColorScheme.primary color. If the button
/// is not enabled then the colorScheme's [ColorScheme.onSurface] color
/// with opacity 0.12.
Color getFillColor(MaterialButton button) {
final Color fillColor = button.enabled ? button.color : button.disabledColor;
Color? getFillColor(MaterialButton button) {
final Color? fillColor = button.enabled ? button.color : button.disabledColor;
if (fillColor != null)
return fillColor;
......@@ -608,15 +603,12 @@ class ButtonThemeData with Diagnosticable {
switch (getTextTheme(button)) {
case ButtonTextTheme.normal:
case ButtonTextTheme.accent:
return button.enabled ? colorScheme.primary : getDisabledFillColor(button);
return button.enabled ? colorScheme!.primary : getDisabledFillColor(button);
case ButtonTextTheme.primary:
return button.enabled
? _buttonColor ?? colorScheme.primary
: colorScheme.onSurface.withOpacity(0.12);
? _buttonColor ?? colorScheme!.primary
: colorScheme!.onSurface.withOpacity(0.12);
}
assert(false);
return null;
}
/// The foreground color of the [button]'s text and icon.
......@@ -641,29 +633,26 @@ class ButtonThemeData with Diagnosticable {
return getDisabledTextColor(button);
if (button.textColor != null)
return button.textColor;
return button.textColor!;
switch (getTextTheme(button)) {
case ButtonTextTheme.normal:
return getBrightness(button) == Brightness.dark ? Colors.white : Colors.black87;
case ButtonTextTheme.accent:
return colorScheme.secondary;
return colorScheme!.secondary;
case ButtonTextTheme.primary:
final Color fillColor = getFillColor(button);
final Color? fillColor = getFillColor(button);
final bool fillIsDark = fillColor != null
? ThemeData.estimateBrightnessForColor(fillColor) == Brightness.dark
: getBrightness(button) == Brightness.dark;
if (fillIsDark)
return Colors.white;
if (button is FlatButton || button is OutlineButton)
return colorScheme.primary;
return colorScheme!.primary;
return Colors.black;
}
assert(false);
return null;
}
/// The color of the ink "splash" overlay that appears when the (enabled)
......@@ -681,16 +670,16 @@ class ButtonThemeData with Diagnosticable {
/// Otherwise, returns [getTextColor] with an opacity of 0.12.
Color getSplashColor(MaterialButton button) {
if (button.splashColor != null)
return button.splashColor;
return button.splashColor!;
if (_splashColor != null && (button is RaisedButton || button is OutlineButton))
return _splashColor;
return _splashColor!;
if (_splashColor != null && button is FlatButton) {
switch (getTextTheme(button)) {
case ButtonTextTheme.normal:
case ButtonTextTheme.accent:
return _splashColor;
return _splashColor!;
case ButtonTextTheme.primary:
break;
}
......@@ -736,7 +725,7 @@ class ButtonThemeData with Diagnosticable {
/// * [ButtonTextTheme.primary], returns [Colors.transparent].
Color getHighlightColor(MaterialButton button) {
if (button.highlightColor != null)
return button.highlightColor;
return button.highlightColor!;
switch (getTextTheme(button)) {
case ButtonTextTheme.normal:
......@@ -745,9 +734,6 @@ class ButtonThemeData with Diagnosticable {
case ButtonTextTheme.primary:
return Colors.transparent;
}
assert(false);
return Colors.transparent;
}
/// The [button]'s elevation when it is enabled and has not been pressed.
......@@ -757,7 +743,7 @@ class ButtonThemeData with Diagnosticable {
/// If button is a [FlatButton] then elevation is 0.0, otherwise it is 2.0.
double getElevation(MaterialButton button) {
if (button.elevation != null)
return button.elevation;
return button.elevation!;
if (button is FlatButton)
return 0.0;
return 2.0;
......@@ -771,7 +757,7 @@ class ButtonThemeData with Diagnosticable {
/// elevation is 0.0, otherwise the highlight elevation is 4.0.
double getFocusElevation(MaterialButton button) {
if (button.focusElevation != null)
return button.focusElevation;
return button.focusElevation!;
if (button is FlatButton)
return 0.0;
if (button is OutlineButton)
......@@ -787,7 +773,7 @@ class ButtonThemeData with Diagnosticable {
/// elevation is 0.0, otherwise the highlight elevation is 4.0.
double getHoverElevation(MaterialButton button) {
if (button.hoverElevation != null)
return button.hoverElevation;
return button.hoverElevation!;
if (button is FlatButton)
return 0.0;
if (button is OutlineButton)
......@@ -803,7 +789,7 @@ class ButtonThemeData with Diagnosticable {
/// elevation is 0.0, otherwise the highlight elevation is 8.0.
double getHighlightElevation(MaterialButton button) {
if (button.highlightElevation != null)
return button.highlightElevation;
return button.highlightElevation!;
if (button is FlatButton)
return 0.0;
if (button is OutlineButton)
......@@ -819,7 +805,7 @@ class ButtonThemeData with Diagnosticable {
/// Otherwise the disabled elevation is 0.0.
double getDisabledElevation(MaterialButton button) {
if (button.disabledElevation != null)
return button.disabledElevation;
return button.disabledElevation!;
return 0.0;
}
......@@ -838,13 +824,13 @@ class ButtonThemeData with Diagnosticable {
/// otherwise.
EdgeInsetsGeometry getPadding(MaterialButton button) {
if (button.padding != null)
return button.padding;
return button.padding!;
if (button is MaterialButtonWithIconMixin)
return const EdgeInsetsDirectional.only(start: 12.0, end: 16.0);
if (_padding != null)
return _padding;
return _padding!;
switch (getTextTheme(button)) {
case ButtonTextTheme.normal:
......@@ -853,8 +839,6 @@ class ButtonThemeData with Diagnosticable {
case ButtonTextTheme.primary:
return const EdgeInsets.symmetric(horizontal: 24.0);
}
assert(false);
return EdgeInsets.zero;
}
/// The shape of the [button]'s [Material].
......@@ -895,21 +879,21 @@ class ButtonThemeData with Diagnosticable {
/// Creates a copy of this button theme data object with the matching fields
/// replaced with the non-null parameter values.
ButtonThemeData copyWith({
ButtonTextTheme textTheme,
ButtonBarLayoutBehavior layoutBehavior,
double minWidth,
double height,
EdgeInsetsGeometry padding,
ShapeBorder shape,
bool alignedDropdown,
Color buttonColor,
Color disabledColor,
Color focusColor,
Color hoverColor,
Color highlightColor,
Color splashColor,
ColorScheme colorScheme,
MaterialTapTargetSize materialTapTargetSize,
ButtonTextTheme? textTheme,
ButtonBarLayoutBehavior? layoutBehavior,
double? minWidth,
double? height,
EdgeInsetsGeometry? padding,
ShapeBorder? shape,
bool? alignedDropdown,
Color? buttonColor,
Color? disabledColor,
Color? focusColor,
Color? hoverColor,
Color? highlightColor,
Color? splashColor,
ColorScheme? colorScheme,
MaterialTapTargetSize? materialTapTargetSize,
}) {
return ButtonThemeData(
textTheme: textTheme ?? this.textTheme,
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:ui';
import 'package:flutter/foundation.dart';
......@@ -65,8 +63,8 @@ class MaterialButton extends StatelessWidget {
/// [highlightElevation], and [disabledElevation] must be non-negative, if
/// specified.
const MaterialButton({
Key key,
@required this.onPressed,
Key? key,
required this.onPressed,
this.onLongPress,
this.onHighlightChanged,
this.mouseCursor,
......@@ -113,7 +111,7 @@ class MaterialButton extends StatelessWidget {
/// See also:
///
/// * [enabled], which is true if the button is enabled.
final VoidCallback onPressed;
final VoidCallback? onPressed;
/// The callback that is called when the button is long-pressed.
///
......@@ -122,7 +120,7 @@ class MaterialButton extends StatelessWidget {
/// See also:
///
/// * [enabled], which is true if the button is enabled.
final VoidCallback onLongPress;
final VoidCallback? onLongPress;
/// Called by the underlying [InkWell] widget's [InkWell.onHighlightChanged]
/// callback.
......@@ -130,16 +128,16 @@ class MaterialButton extends StatelessWidget {
/// If [onPressed] changes from null to non-null while a gesture is ongoing,
/// this can fire during the build phase (in which case calling
/// [State.setState] is not allowed).
final ValueChanged<bool> onHighlightChanged;
final ValueChanged<bool>? onHighlightChanged;
/// {@macro flutter.material.button.mouseCursor}
final MouseCursor mouseCursor;
final MouseCursor? mouseCursor;
/// Defines the button's base colors, and the defaults for the button's minimum
/// size, internal padding, and shape.
///
/// Defaults to `ButtonTheme.of(context).textTheme`.
final ButtonTextTheme textTheme;
final ButtonTextTheme? textTheme;
/// The color to use for this button's text.
///
......@@ -157,7 +155,7 @@ class MaterialButton extends StatelessWidget {
///
/// * [disabledTextColor], the text color to use when the button has been
/// disabled.
final Color textColor;
final Color? textColor;
/// The color to use for this button's text when the button is disabled.
///
......@@ -174,7 +172,7 @@ class MaterialButton extends StatelessWidget {
/// See also:
///
/// * [textColor] - The color to use for this button's text when the button is [enabled].
final Color disabledTextColor;
final Color? disabledTextColor;
/// The button's fill color, displayed by its [Material], while it
/// is in its default (unpressed, [enabled]) state.
......@@ -184,7 +182,7 @@ class MaterialButton extends StatelessWidget {
/// See also:
///
/// * [disabledColor] - the fill color of the button when the button is disabled.
final Color color;
final Color? color;
/// The fill color of the button when the button is disabled.
///
......@@ -194,7 +192,7 @@ class MaterialButton extends StatelessWidget {
/// See also:
///
/// * [color] - the fill color of the button when the button is [enabled].
final Color disabledColor;
final Color? disabledColor;
/// The splash color of the button's [InkWell].
///
......@@ -207,20 +205,20 @@ class MaterialButton extends StatelessWidget {
///
/// The appearance of the splash can be configured with the theme's splash
/// factory, [ThemeData.splashFactory].
final Color splashColor;
final Color? splashColor;
/// The fill color of the button's [Material] when it has the input focus.
///
/// The button changed focus color when the button has the input focus. It
/// appears behind the button's child.
final Color focusColor;
final Color? focusColor;
/// The fill color of the button's [Material] when a pointer is hovering over
/// it.
///
/// The button changes fill color when a pointer is hovering over the button.
/// It appears behind the button's child.
final Color hoverColor;
final Color? hoverColor;
/// The highlight color of the button's [InkWell].
///
......@@ -231,7 +229,7 @@ class MaterialButton extends StatelessWidget {
/// If [textTheme] is [ButtonTextTheme.primary], the default highlight color is
/// transparent (in other words the highlight doesn't appear). Otherwise it's
/// the current theme's highlight color, [ThemeData.highlightColor].
final Color highlightColor;
final Color? highlightColor;
/// The z-coordinate at which to place this button relative to its parent.
///
......@@ -248,7 +246,7 @@ class MaterialButton extends StatelessWidget {
/// button.
/// * [disabledElevation], the elevation when the button is disabled.
/// * [highlightElevation], the elevation when the button is pressed.
final double elevation;
final double? elevation;
/// The elevation for the button's [Material] when the button
/// is [enabled] and a pointer is hovering over it.
......@@ -261,7 +259,7 @@ class MaterialButton extends StatelessWidget {
/// * [focusElevation], the elevation when the button is focused.
/// * [disabledElevation], the elevation when the button is disabled.
/// * [highlightElevation], the elevation when the button is pressed.
final double hoverElevation;
final double? hoverElevation;
/// The elevation for the button's [Material] when the button
/// is [enabled] and has the input focus.
......@@ -275,7 +273,7 @@ class MaterialButton extends StatelessWidget {
/// button.
/// * [disabledElevation], the elevation when the button is disabled.
/// * [highlightElevation], the elevation when the button is pressed.
final double focusElevation;
final double? focusElevation;
/// The elevation for the button's [Material] relative to its parent when the
/// button is [enabled] and pressed.
......@@ -293,7 +291,7 @@ class MaterialButton extends StatelessWidget {
/// * [hoverElevation], the elevation when a pointer is hovering over the
/// button.
/// * [disabledElevation], the elevation when the button is disabled.
final double highlightElevation;
final double? highlightElevation;
/// The elevation for the button's [Material] relative to its parent when the
/// button is not [enabled].
......@@ -304,7 +302,7 @@ class MaterialButton extends StatelessWidget {
///
/// * [elevation], the default elevation.
/// * [highlightElevation], the elevation when the button is pressed.
final double disabledElevation;
final double? disabledElevation;
/// The theme brightness to use for this button.
///
......@@ -315,12 +313,12 @@ class MaterialButton extends StatelessWidget {
/// See also:
///
/// * [ButtonTextTheme], uses [Brightness] to determine text color.
final Brightness colorBrightness;
final Brightness? colorBrightness;
/// The button's label.
///
/// Often a [Text] widget in all caps.
final Widget child;
final Widget? child;
/// Whether the button is enabled or disabled.
///
......@@ -332,7 +330,7 @@ class MaterialButton extends StatelessWidget {
///
/// Defaults to the value from the current [ButtonTheme],
/// [ButtonThemeData.padding].
final EdgeInsetsGeometry padding;
final EdgeInsetsGeometry? padding;
/// Defines how compact the button's layout will be.
///
......@@ -342,7 +340,7 @@ class MaterialButton extends StatelessWidget {
///
/// * [ThemeData.visualDensity], which specifies the [visualDensity] for all
/// widgets within a [Theme].
final VisualDensity visualDensity;
final VisualDensity? visualDensity;
/// The shape of the button's [Material].
///
......@@ -352,7 +350,7 @@ class MaterialButton extends StatelessWidget {
///
/// Defaults to the value from the current [ButtonTheme],
/// [ButtonThemeData.shape].
final ShapeBorder shape;
final ShapeBorder? shape;
/// {@macro flutter.widgets.Clip}
///
......@@ -360,7 +358,7 @@ class MaterialButton extends StatelessWidget {
final Clip clipBehavior;
/// {@macro flutter.widgets.Focus.focusNode}
final FocusNode focusNode;
final FocusNode? focusNode;
/// {@macro flutter.widgets.Focus.autofocus}
final bool autofocus;
......@@ -368,7 +366,7 @@ class MaterialButton extends StatelessWidget {
/// Defines the duration of animated changes for [shape] and [elevation].
///
/// The default value is [kThemeChangeDuration].
final Duration animationDuration;
final Duration? animationDuration;
/// Configures the minimum size of the tap target.
///
......@@ -377,17 +375,17 @@ class MaterialButton extends StatelessWidget {
/// See also:
///
/// * [MaterialTapTargetSize], for a description of how this affects tap targets.
final MaterialTapTargetSize materialTapTargetSize;
final MaterialTapTargetSize? materialTapTargetSize;
/// The smallest horizontal extent that the button will occupy.
///
/// Defaults to the value from the current [ButtonTheme].
final double minWidth;
final double? minWidth;
/// The vertical extent of the button.
///
/// Defaults to the value from the current [ButtonTheme].
final double height;
final double? height;
/// Whether detected gestures should provide acoustic and/or haptic feedback.
///
......@@ -401,7 +399,7 @@ class MaterialButton extends StatelessWidget {
@override
Widget build(BuildContext context) {
final ThemeData theme = Theme.of(context);
final ThemeData theme = Theme.of(context)!;
final ButtonThemeData buttonTheme = ButtonTheme.of(context);
return RawMaterialButton(
......@@ -411,9 +409,9 @@ class MaterialButton extends StatelessWidget {
onHighlightChanged: onHighlightChanged,
mouseCursor: mouseCursor,
fillColor: buttonTheme.getFillColor(this),
textStyle: theme.textTheme.button.copyWith(color: buttonTheme.getTextColor(this)),
focusColor: focusColor ?? buttonTheme.getFocusColor(this) ?? theme.focusColor,
hoverColor: hoverColor ?? buttonTheme.getHoverColor(this) ?? theme.hoverColor,
textStyle: theme.textTheme.button!.copyWith(color: buttonTheme.getTextColor(this)),
focusColor: focusColor ?? buttonTheme.getFocusColor(this),
hoverColor: hoverColor ?? buttonTheme.getHoverColor(this),
highlightColor: highlightColor ?? theme.highlightColor,
splashColor: splashColor ?? theme.splashColor,
elevation: buttonTheme.getElevation(this),
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:async';
import 'dart:collection';
import 'dart:math' as math;
......@@ -75,15 +73,15 @@ class ScaffoldPrelayoutGeometry {
/// Abstract const constructor. This constructor enables subclasses to provide
/// const constructors so that they can be used in const expressions.
const ScaffoldPrelayoutGeometry({
@required this.bottomSheetSize,
@required this.contentBottom,
@required this.contentTop,
@required this.floatingActionButtonSize,
@required this.minInsets,
@required this.minViewPadding,
@required this.scaffoldSize,
@required this.snackBarSize,
@required this.textDirection,
required this.bottomSheetSize,
required this.contentBottom,
required this.contentTop,
required this.floatingActionButtonSize,
required this.minInsets,
required this.minViewPadding,
required this.scaffoldSize,
required this.snackBarSize,
required this.textDirection,
});
/// The [Size] of [Scaffold.floatingActionButton].
......@@ -225,12 +223,12 @@ class ScaffoldGeometry {
/// rectangle in which the [Scaffold.bottomNavigationBar] bar is laid out.
///
/// Null if [Scaffold.bottomNavigationBar] is null.
final double bottomNavigationBarTop;
final double? bottomNavigationBarTop;
/// The [Scaffold.floatingActionButton]'s bounding rectangle.
///
/// This is null when there is no floating action button showing.
final Rect floatingActionButtonArea;
final Rect? floatingActionButtonArea;
ScaffoldGeometry _scaleFloatingActionButton(double scaleFactor) {
if (scaleFactor == 1.0)
......@@ -243,18 +241,18 @@ class ScaffoldGeometry {
}
final Rect scaledButton = Rect.lerp(
floatingActionButtonArea.center & Size.zero,
floatingActionButtonArea!.center & Size.zero,
floatingActionButtonArea,
scaleFactor,
);
)!;
return copyWith(floatingActionButtonArea: scaledButton);
}
/// Creates a copy of this [ScaffoldGeometry] but with the given fields replaced with
/// the new values.
ScaffoldGeometry copyWith({
double bottomNavigationBarTop,
Rect floatingActionButtonArea,
double? bottomNavigationBarTop,
Rect? floatingActionButtonArea,
}) {
return ScaffoldGeometry(
bottomNavigationBarTop: bottomNavigationBarTop ?? this.bottomNavigationBarTop,
......@@ -268,14 +266,14 @@ class _ScaffoldGeometryNotifier extends ChangeNotifier implements ValueListenabl
: assert (context != null);
final BuildContext context;
double floatingActionButtonScale;
double? floatingActionButtonScale;
ScaffoldGeometry geometry;
@override
ScaffoldGeometry get value {
assert(() {
final RenderObject renderObject = context.findRenderObject();
if (renderObject == null || !renderObject.owner.debugDoingPaint)
final RenderObject? renderObject = context.findRenderObject();
if (renderObject == null || !renderObject.owner!.debugDoingPaint)
throw FlutterError(
'Scaffold.geometryOf() must only be accessed during the paint phase.\n'
'The ScaffoldGeometry is only available during the paint phase, because '
......@@ -283,13 +281,13 @@ class _ScaffoldGeometryNotifier extends ChangeNotifier implements ValueListenabl
);
return true;
}());
return geometry._scaleFloatingActionButton(floatingActionButtonScale);
return geometry._scaleFloatingActionButton(floatingActionButtonScale!);
}
void _updateWith({
double bottomNavigationBarTop,
Rect floatingActionButtonArea,
double floatingActionButtonScale,
double? bottomNavigationBarTop,
Rect? floatingActionButtonArea,
double? floatingActionButtonScale,
}) {
this.floatingActionButtonScale = floatingActionButtonScale ?? this.floatingActionButtonScale;
geometry = geometry.copyWith(
......@@ -315,8 +313,8 @@ class _BodyBoxConstraints extends BoxConstraints {
double maxWidth = double.infinity,
double minHeight = 0.0,
double maxHeight = double.infinity,
@required this.bottomWidgetsHeight,
@required this.appBarHeight,
required this.bottomWidgetsHeight,
required this.appBarHeight,
}) : assert(bottomWidgetsHeight != null),
assert(bottomWidgetsHeight >= 0),
assert(appBarHeight != null),
......@@ -353,10 +351,10 @@ class _BodyBoxConstraints extends BoxConstraints {
// The constraints parameter is constructed in_ScaffoldLayout.performLayout().
class _BodyBuilder extends StatelessWidget {
const _BodyBuilder({
Key key,
@required this.extendBody,
@required this.extendBodyBehindAppBar,
@required this.body,
Key? key,
required this.extendBody,
required this.extendBodyBehindAppBar,
required this.body,
}) : assert(extendBody != null),
assert(extendBodyBehindAppBar != null),
assert(body != null),
......@@ -374,7 +372,7 @@ class _BodyBuilder extends StatelessWidget {
return LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
final _BodyBoxConstraints bodyConstraints = constraints as _BodyBoxConstraints;
final MediaQueryData metrics = MediaQuery.of(context);
final MediaQueryData metrics = MediaQuery.of(context)!;
final double bottom = extendBody
? math.max(metrics.padding.bottom, bodyConstraints.bottomWidgetsHeight)
......@@ -400,19 +398,19 @@ class _BodyBuilder extends StatelessWidget {
class _ScaffoldLayout extends MultiChildLayoutDelegate {
_ScaffoldLayout({
@required this.minInsets,
@required this.minViewPadding,
@required this.textDirection,
@required this.geometryNotifier,
required this.minInsets,
required this.minViewPadding,
required this.textDirection,
required this.geometryNotifier,
// for floating action button
@required this.previousFloatingActionButtonLocation,
@required this.currentFloatingActionButtonLocation,
@required this.floatingActionButtonMoveAnimationProgress,
@required this.floatingActionButtonMotionAnimator,
@required this.isSnackBarFloating,
@required this.snackBarWidth,
@required this.extendBody,
@required this.extendBodyBehindAppBar,
required this.previousFloatingActionButtonLocation,
required this.currentFloatingActionButtonLocation,
required this.floatingActionButtonMoveAnimationProgress,
required this.floatingActionButtonMotionAnimator,
required this.isSnackBarFloating,
required this.snackBarWidth,
required this.extendBody,
required this.extendBodyBehindAppBar,
}) : assert(minInsets != null),
assert(textDirection != null),
assert(geometryNotifier != null),
......@@ -434,7 +432,7 @@ class _ScaffoldLayout extends MultiChildLayoutDelegate {
final FloatingActionButtonAnimator floatingActionButtonMotionAnimator;
final bool isSnackBarFloating;
final double snackBarWidth;
final double? snackBarWidth;
@override
void performLayout(Size size) {
......@@ -457,7 +455,7 @@ class _ScaffoldLayout extends MultiChildLayoutDelegate {
positionChild(_ScaffoldSlot.appBar, Offset.zero);
}
double bottomNavigationBarTop;
double? bottomNavigationBarTop;
if (hasChild(_ScaffoldSlot.bottomNavigationBar)) {
final double bottomNavigationBarHeight = layoutChild(_ScaffoldSlot.bottomNavigationBar, fullWidthConstraints).height;
bottomWidgetsHeight += bottomNavigationBarHeight;
......@@ -537,7 +535,7 @@ class _ScaffoldLayout extends MultiChildLayoutDelegate {
positionChild(_ScaffoldSlot.bottomSheet, Offset((size.width - bottomSheetSize.width) / 2.0, contentBottom - bottomSheetSize.height));
}
Rect floatingActionButtonRect;
late Rect floatingActionButtonRect;
if (hasChild(_ScaffoldSlot.floatingActionButton)) {
final Size fabSize = layoutChild(_ScaffoldSlot.floatingActionButton, looseConstraints);
......@@ -566,7 +564,7 @@ class _ScaffoldLayout extends MultiChildLayoutDelegate {
}
if (hasChild(_ScaffoldSlot.snackBar)) {
final bool hasCustomWidth = snackBarWidth != null && snackBarWidth < size.width;
final bool hasCustomWidth = snackBarWidth != null && snackBarWidth! < size.width;
if (snackBarSize == Size.zero) {
snackBarSize = layoutChild(
_ScaffoldSlot.snackBar,
......@@ -589,7 +587,7 @@ class _ScaffoldLayout extends MultiChildLayoutDelegate {
: contentBottom;
}
final double xOffset = hasCustomWidth ? (size.width - snackBarWidth) / 2 : 0.0;
final double xOffset = hasCustomWidth ? (size.width - snackBarWidth!) / 2 : 0.0;
positionChild(_ScaffoldSlot.snackBar, Offset(xOffset, snackBarYOffsetBase - snackBarSize.height));
}
......@@ -636,18 +634,18 @@ class _ScaffoldLayout extends MultiChildLayoutDelegate {
/// when its [FloatingActionButtonLocation] is updated.
class _FloatingActionButtonTransition extends StatefulWidget {
const _FloatingActionButtonTransition({
Key key,
@required this.child,
@required this.fabMoveAnimation,
@required this.fabMotionAnimator,
@required this.geometryNotifier,
@required this.currentController,
Key? key,
required this.child,
required this.fabMoveAnimation,
required this.fabMotionAnimator,
required this.geometryNotifier,
required this.currentController,
}) : assert(fabMoveAnimation != null),
assert(fabMotionAnimator != null),
assert(currentController != null),
super(key: key);
final Widget child;
final Widget? child;
final Animation<double> fabMoveAnimation;
final FloatingActionButtonAnimator fabMotionAnimator;
final _ScaffoldGeometryNotifier geometryNotifier;
......@@ -662,14 +660,14 @@ class _FloatingActionButtonTransition extends StatefulWidget {
class _FloatingActionButtonTransitionState extends State<_FloatingActionButtonTransition> with TickerProviderStateMixin {
// The animations applied to the Floating Action Button when it is entering or exiting.
// Controls the previous widget.child as it exits.
AnimationController _previousController;
Animation<double> _previousScaleAnimation;
Animation<double> _previousRotationAnimation;
late AnimationController _previousController;
late Animation<double> _previousScaleAnimation;
late Animation<double> _previousRotationAnimation;
// The animations to run, considering the widget's fabMoveAnimation and the current/previous entrance/exit animations.
Animation<double> _currentScaleAnimation;
Animation<double> _extendedCurrentScaleAnimation;
Animation<double> _currentRotationAnimation;
Widget _previousChild;
late Animation<double> _currentScaleAnimation;
late Animation<double> _extendedCurrentScaleAnimation;
late Animation<double> _currentRotationAnimation;
Widget? _previousChild;
@override
void initState() {
......@@ -780,7 +778,7 @@ class _FloatingActionButtonTransitionState extends State<_FloatingActionButtonTr
});
}
bool _isExtendedFloatingActionButton(Widget widget) {
bool _isExtendedFloatingActionButton(Widget? widget) {
return widget is FloatingActionButton
&& widget.isExtended;
}
......@@ -1025,7 +1023,7 @@ class _FloatingActionButtonTransitionState extends State<_FloatingActionButtonTr
class Scaffold extends StatefulWidget {
/// Creates a visual scaffold for material design widgets.
const Scaffold({
Key key,
Key? key,
this.appBar,
this.body,
this.floatingActionButton,
......@@ -1089,7 +1087,7 @@ class Scaffold extends StatefulWidget {
final bool extendBodyBehindAppBar;
/// An app bar to display at the top of the scaffold.
final PreferredSizeWidget appBar;
final PreferredSizeWidget? appBar;
/// The primary content of the scaffold.
///
......@@ -1109,22 +1107,22 @@ class Scaffold extends StatefulWidget {
/// but may overflow and would in such cases need to scroll, consider using a
/// [ListView] as the body of the scaffold. This is also a good choice for
/// the case where your body is a scrollable list.
final Widget body;
final Widget? body;
/// A button displayed floating above [body], in the bottom right corner.
///
/// Typically a [FloatingActionButton].
final Widget floatingActionButton;
final Widget? floatingActionButton;
/// Responsible for determining where the [floatingActionButton] should go.
///
/// If null, the [ScaffoldState] will use the default location, [FloatingActionButtonLocation.endFloat].
final FloatingActionButtonLocation floatingActionButtonLocation;
final FloatingActionButtonLocation? floatingActionButtonLocation;
/// Animator to move the [floatingActionButton] to a new [floatingActionButtonLocation].
///
/// If null, the [ScaffoldState] will use the default animator, [FloatingActionButtonAnimator.scaling].
final FloatingActionButtonAnimator floatingActionButtonAnimator;
final FloatingActionButtonAnimator? floatingActionButtonAnimator;
/// A set of buttons that are displayed at the bottom of the scaffold.
///
......@@ -1135,7 +1133,7 @@ class Scaffold extends StatefulWidget {
///
/// The [persistentFooterButtons] are rendered above the
/// [bottomNavigationBar] but below the [body].
final List<Widget> persistentFooterButtons;
final List<Widget>? persistentFooterButtons;
/// A panel displayed to the side of the [body], often hidden on mobile
/// devices. Swipes in from either left-to-right ([TextDirection.ltr]) or
......@@ -1195,7 +1193,7 @@ class Scaffold extends StatefulWidget {
/// }
/// ```
/// {@end-tool}
final Widget drawer;
final Widget? drawer;
/// A panel displayed to the side of the [body], often hidden on mobile
/// devices. Swipes in from right-to-left ([TextDirection.ltr]) or
......@@ -1255,17 +1253,17 @@ class Scaffold extends StatefulWidget {
/// }
/// ```
/// {@end-tool}
final Widget endDrawer;
final Widget? endDrawer;
/// The color to use for the scrim that obscures primary content while a drawer is open.
///
/// By default, the color is [Colors.black54]
final Color drawerScrimColor;
final Color? drawerScrimColor;
/// The color of the [Material] widget that underlies the entire Scaffold.
///
/// The theme's [ThemeData.scaffoldBackgroundColor] by default.
final Color backgroundColor;
final Color? backgroundColor;
/// A bottom navigation bar to display at the bottom of the scaffold.
///
......@@ -1274,7 +1272,7 @@ class Scaffold extends StatefulWidget {
///
/// The [bottomNavigationBar] is rendered below the [persistentFooterButtons]
/// and the [body].
final Widget bottomNavigationBar;
final Widget? bottomNavigationBar;
/// The persistent bottom sheet to display.
///
......@@ -1305,7 +1303,7 @@ class Scaffold extends StatefulWidget {
/// * [showBottomSheet], which displays a bottom sheet as a route that can
/// be dismissed with the scaffold's back button.
/// * [showModalBottomSheet], which displays a modal bottom sheet.
final Widget bottomSheet;
final Widget? bottomSheet;
/// This flag is deprecated, please use [resizeToAvoidBottomInset]
/// instead.
......@@ -1317,7 +1315,7 @@ class Scaffold extends StatefulWidget {
'Use resizeToAvoidBottomInset to specify if the body should resize when the keyboard appears. '
'This feature was deprecated after v1.1.9.'
)
final bool resizeToAvoidBottomPadding;
final bool? resizeToAvoidBottomPadding;
/// If true the [body] and the scaffold's floating widgets should size
/// themselves to avoid the onscreen keyboard whose height is defined by the
......@@ -1328,7 +1326,7 @@ class Scaffold extends StatefulWidget {
/// prevents widgets inside the body from being obscured by the keyboard.
///
/// Defaults to true.
final bool resizeToAvoidBottomInset;
final bool? resizeToAvoidBottomInset;
/// Whether this scaffold is being displayed at the top of the screen.
///
......@@ -1351,7 +1349,7 @@ class Scaffold extends StatefulWidget {
/// not obscured. For example, if `TextDirection.of(context)` is set to
/// [TextDirection.ltr], 20.0 will be added to
/// `MediaQuery.of(context).padding.left`.
final double drawerEdgeDragWidth;
final double? drawerEdgeDragWidth;
/// Determines if the [Scaffold.drawer] can be opened with a drag
/// gesture.
......@@ -1467,10 +1465,10 @@ class Scaffold extends StatefulWidget {
///
/// If there is no [Scaffold] in scope, then this will throw an exception.
/// To return null if there is no [Scaffold], then pass `nullOk: true`.
static ScaffoldState of(BuildContext context, { bool nullOk = false }) {
static ScaffoldState? of(BuildContext context, { bool nullOk = false }) {
assert(nullOk != null);
assert(context != null);
final ScaffoldState result = context.findAncestorStateOfType<ScaffoldState>();
final ScaffoldState? result = context.findAncestorStateOfType<ScaffoldState>();
if (nullOk || result != null)
return result;
throw FlutterError.fromParts(<DiagnosticsNode>[
......@@ -1521,8 +1519,8 @@ class Scaffold extends StatefulWidget {
/// return value with the previous listenable, if it has changed, unregister
/// the listener, and register a listener to the new [ScaffoldGeometry]
/// listenable.
static ValueListenable<ScaffoldGeometry> geometryOf(BuildContext context) {
final _ScaffoldScope scaffoldScope = context.dependOnInheritedWidgetOfExactType<_ScaffoldScope>();
static ValueListenable<ScaffoldGeometry>? geometryOf(BuildContext context) {
final _ScaffoldScope? scaffoldScope = context.dependOnInheritedWidgetOfExactType<_ScaffoldScope>();
if (scaffoldScope == null)
throw FlutterError.fromParts(<DiagnosticsNode>[
ErrorSummary(
......@@ -1566,10 +1564,10 @@ class Scaffold extends StatefulWidget {
assert(registerForUpdates != null);
assert(context != null);
if (registerForUpdates) {
final _ScaffoldScope scaffold = context.dependOnInheritedWidgetOfExactType<_ScaffoldScope>();
final _ScaffoldScope? scaffold = context.dependOnInheritedWidgetOfExactType<_ScaffoldScope>();
return scaffold?.hasDrawer ?? false;
} else {
final ScaffoldState scaffold = context.findAncestorStateOfType<ScaffoldState>();
final ScaffoldState? scaffold = context.findAncestorStateOfType<ScaffoldState>();
return scaffold?.hasDrawer ?? false;
}
}
......@@ -1598,11 +1596,11 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin {
/// Whether this scaffold has a non-null [Scaffold.floatingActionButton].
bool get hasFloatingActionButton => widget.floatingActionButton != null;
double _appBarMaxHeight;
double? _appBarMaxHeight;
/// The max height the [Scaffold.appBar] uses.
///
/// This is based on the appBar preferred height plus the top padding.
double get appBarMaxHeight => _appBarMaxHeight;
double? get appBarMaxHeight => _appBarMaxHeight;
bool _drawerOpened = false;
bool _endDrawerOpened = false;
......@@ -1648,7 +1646,7 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin {
/// See [Scaffold.of] for information about how to obtain the [ScaffoldState].
void openDrawer() {
if (_endDrawerKey.currentState != null && _endDrawerOpened)
_endDrawerKey.currentState.close();
_endDrawerKey.currentState!.close();
_drawerKey.currentState?.open();
}
......@@ -1666,16 +1664,16 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin {
/// See [Scaffold.of] for information about how to obtain the [ScaffoldState].
void openEndDrawer() {
if (_drawerKey.currentState != null && _drawerOpened)
_drawerKey.currentState.close();
_drawerKey.currentState!.close();
_endDrawerKey.currentState?.open();
}
// SNACKBAR API
final Queue<ScaffoldFeatureController<SnackBar, SnackBarClosedReason>> _snackBars = Queue<ScaffoldFeatureController<SnackBar, SnackBarClosedReason>>();
AnimationController _snackBarController;
Timer _snackBarTimer;
bool _accessibleNavigation;
AnimationController? _snackBarController;
Timer? _snackBarTimer;
bool? _accessibleNavigation;
/// Shows a [SnackBar] at the bottom of the scaffold.
///
......@@ -1716,15 +1714,15 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin {
_snackBarController ??= SnackBar.createAnimationController(vsync: this)
..addStatusListener(_handleSnackBarStatusChange);
if (_snackBars.isEmpty) {
assert(_snackBarController.isDismissed);
_snackBarController.forward();
assert(_snackBarController!.isDismissed);
_snackBarController!.forward();
}
ScaffoldFeatureController<SnackBar, SnackBarClosedReason> controller;
late 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()),
snackbar.withAnimation(_snackBarController!, fallbackKey: UniqueKey()),
Completer<SnackBarClosedReason>(),
() {
assert(_snackBars.first == controller);
......@@ -1746,7 +1744,7 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin {
_snackBars.removeFirst();
});
if (_snackBars.isNotEmpty)
_snackBarController.forward();
_snackBarController!.forward();
break;
case AnimationStatus.completed:
setState(() {
......@@ -1773,7 +1771,7 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin {
completer.complete(reason);
_snackBarTimer?.cancel();
_snackBarTimer = null;
_snackBarController.value = 0.0;
_snackBarController!.value = 0.0;
}
/// Removes the current [SnackBar] by running its normal exit animation.
......@@ -1781,15 +1779,15 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin {
/// 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)
if (_snackBars.isEmpty || _snackBarController!.status == AnimationStatus.dismissed)
return;
final MediaQueryData mediaQuery = MediaQuery.of(context);
final MediaQueryData mediaQuery = MediaQuery.of(context)!;
final Completer<SnackBarClosedReason> completer = _snackBars.first._completer;
if (mediaQuery.accessibleNavigation) {
_snackBarController.value = 0.0;
_snackBarController!.value = 0.0;
completer.complete(reason);
} else {
_snackBarController.reverse().then<void>((void value) {
_snackBarController!.reverse().then<void>((void value) {
assert(mounted);
if (!completer.isCompleted)
completer.complete(reason);
......@@ -1806,7 +1804,7 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin {
// Important if the app/user takes an action that could repeatedly show a
// bottom sheet.
final List<_StandardBottomSheet> _dismissedBottomSheets = <_StandardBottomSheet>[];
PersistentBottomSheetController<dynamic> _currentBottomSheet;
PersistentBottomSheetController<dynamic>? _currentBottomSheet;
void _maybeBuildPersistentBottomSheet() {
if (widget.bottomSheet != null && _currentBottomSheet == null) {
......@@ -1814,7 +1812,7 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin {
// will not be added to the Scaffold's appbar and the bottom sheet will not
// support drag or swipe to dismiss.
final AnimationController animationController = BottomSheet.createAnimationController(this)..value = 1.0;
LocalHistoryEntry _persistentSheetHistoryEntry;
LocalHistoryEntry? _persistentSheetHistoryEntry;
bool _persistentBottomSheetExtentChanged(DraggableScrollableNotification notification) {
if (notification.extent > notification.initialExtent) {
if (_persistentSheetHistoryEntry == null) {
......@@ -1826,10 +1824,10 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin {
_floatingActionButtonVisibilityValue = 1.0;
_persistentSheetHistoryEntry = null;
});
ModalRoute.of(context).addLocalHistoryEntry(_persistentSheetHistoryEntry);
ModalRoute.of(context)!.addLocalHistoryEntry(_persistentSheetHistoryEntry!);
}
} else if (_persistentSheetHistoryEntry != null) {
ModalRoute.of(context).removeLocalHistoryEntry(_persistentSheetHistoryEntry);
ModalRoute.of(context)!.removeLocalHistoryEntry(_persistentSheetHistoryEntry!);
}
return false;
}
......@@ -1839,7 +1837,7 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin {
return NotificationListener<DraggableScrollableNotification>(
onNotification: _persistentBottomSheetExtentChanged,
child: DraggableScrollableActuator(
child: widget.bottomSheet,
child: widget.bottomSheet!,
),
);
},
......@@ -1851,11 +1849,11 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin {
void _closeCurrentBottomSheet() {
if (_currentBottomSheet != null) {
if (!_currentBottomSheet._isLocalHistoryEntry) {
_currentBottomSheet.close();
if (!_currentBottomSheet!._isLocalHistoryEntry) {
_currentBottomSheet!.close();
}
assert(() {
_currentBottomSheet?._completer?.future?.whenComplete(() {
_currentBottomSheet?._completer.future.whenComplete(() {
assert(_currentBottomSheet == null);
});
return true;
......@@ -1866,11 +1864,11 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin {
PersistentBottomSheetController<T> _buildBottomSheet<T>(
WidgetBuilder builder,
bool isPersistent, {
AnimationController animationController,
Color backgroundColor,
double elevation,
ShapeBorder shape,
Clip clipBehavior,
required AnimationController animationController,
Color? backgroundColor,
double? elevation,
ShapeBorder? shape,
Clip? clipBehavior,
}) {
assert(() {
if (widget.bottomSheet != null && isPersistent && _currentBottomSheet != null) {
......@@ -1885,7 +1883,7 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin {
final Completer<T> completer = Completer<T>();
final GlobalKey<_StandardBottomSheetState> bottomSheetKey = GlobalKey<_StandardBottomSheetState>();
_StandardBottomSheet bottomSheet;
late _StandardBottomSheet bottomSheet;
bool removedEntry = false;
void _removeCurrentBottomSheet() {
......@@ -1893,7 +1891,7 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin {
if (_currentBottomSheet == null) {
return;
}
assert(_currentBottomSheet._widget == bottomSheet);
assert(_currentBottomSheet!._widget == bottomSheet);
assert(bottomSheetKey.currentState != null);
_showFloatingActionButton();
......@@ -1908,7 +1906,7 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin {
completer.complete();
}
final Future<void> closing = bottomSheetKey.currentState.close();
final Future<void>? closing = bottomSheetKey.currentState?.close();
if (closing != null) {
closing.then(_closed);
} else {
......@@ -1916,7 +1914,7 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin {
}
}
final LocalHistoryEntry entry = isPersistent
final LocalHistoryEntry? entry = isPersistent
? null
: LocalHistoryEntry(onRemove: () {
if (!removedEntry) {
......@@ -1932,10 +1930,10 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin {
if (_currentBottomSheet == null) {
return;
}
assert(_currentBottomSheet._widget == bottomSheet);
assert(_currentBottomSheet!._widget == bottomSheet);
if (!isPersistent && !removedEntry) {
assert(entry != null);
entry.remove();
entry!.remove();
removedEntry = true;
}
},
......@@ -1955,7 +1953,7 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin {
);
if (!isPersistent)
ModalRoute.of(context).addLocalHistoryEntry(entry);
ModalRoute.of(context)!.addLocalHistoryEntry(entry!);
return PersistentBottomSheetController<T>._(
bottomSheet,
......@@ -2045,10 +2043,10 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin {
/// * <https://material.io/design/components/sheets-bottom.html#standard-bottom-sheet>
PersistentBottomSheetController<T> showBottomSheet<T>(
WidgetBuilder builder, {
Color backgroundColor,
double elevation,
ShapeBorder shape,
Clip clipBehavior,
Color? backgroundColor,
double? elevation,
ShapeBorder? shape,
Clip? clipBehavior,
}) {
assert(() {
if (widget.bottomSheet != null) {
......@@ -2079,12 +2077,12 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin {
}
// Floating Action Button API
AnimationController _floatingActionButtonMoveController;
FloatingActionButtonAnimator _floatingActionButtonAnimator;
FloatingActionButtonLocation _previousFloatingActionButtonLocation;
FloatingActionButtonLocation _floatingActionButtonLocation;
late AnimationController _floatingActionButtonMoveController;
late FloatingActionButtonAnimator _floatingActionButtonAnimator;
FloatingActionButtonLocation? _previousFloatingActionButtonLocation;
FloatingActionButtonLocation? _floatingActionButtonLocation;
AnimationController _floatingActionButtonVisibilityController;
late AnimationController _floatingActionButtonVisibilityController;
/// Gets the current value of the visibility animation for the
/// [Scaffold.floatingActionButton].
......@@ -2097,7 +2095,7 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin {
_floatingActionButtonVisibilityController.value = newValue.clamp(
_floatingActionButtonVisibilityController.lowerBound,
_floatingActionButtonVisibilityController.upperBound,
) as double;
);
}
/// Shows the [Scaffold.floatingActionButton].
......@@ -2107,11 +2105,11 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin {
// Moves the Floating Action Button to the new Floating Action Button Location.
void _moveFloatingActionButton(final FloatingActionButtonLocation newLocation) {
FloatingActionButtonLocation previousLocation = _floatingActionButtonLocation;
FloatingActionButtonLocation? previousLocation = _floatingActionButtonLocation;
double restartAnimationFrom = 0.0;
// If the Floating Action Button is moving right now, we need to start from a snapshot of the current transition.
if (_floatingActionButtonMoveController.isAnimating) {
previousLocation = _TransitionSnapshotFabLocation(_previousFloatingActionButtonLocation, _floatingActionButtonLocation, _floatingActionButtonAnimator, _floatingActionButtonMoveController.value);
previousLocation = _TransitionSnapshotFabLocation(_previousFloatingActionButtonLocation!, _floatingActionButtonLocation!, _floatingActionButtonAnimator, _floatingActionButtonMoveController.value);
restartAnimationFrom = _floatingActionButtonAnimator.getAnimationRestart(_floatingActionButtonMoveController.value);
}
......@@ -2146,7 +2144,7 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin {
// INTERNALS
_ScaffoldGeometryNotifier _geometryNotifier;
_ScaffoldGeometryNotifier? _geometryNotifier;
// Backwards compatibility for deprecated resizeToAvoidBottomPadding property
bool get _resizeToAvoidBottomInset {
......@@ -2208,7 +2206,7 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin {
@override
void didChangeDependencies() {
final MediaQueryData mediaQuery = MediaQuery.of(context);
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
......@@ -2216,7 +2214,7 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin {
if (_accessibleNavigation == true
&& !mediaQuery.accessibleNavigation
&& _snackBarTimer != null
&& !_snackBarTimer.isActive) {
&& !_snackBarTimer!.isActive) {
hideCurrentSnackBar(reason: SnackBarClosedReason.timeout);
}
_accessibleNavigation = mediaQuery.accessibleNavigation;
......@@ -2229,12 +2227,12 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin {
_snackBarController?.dispose();
_snackBarTimer?.cancel();
_snackBarTimer = null;
_geometryNotifier.dispose();
_geometryNotifier!.dispose();
for (final _StandardBottomSheet bottomSheet in _dismissedBottomSheets) {
bottomSheet.animationController?.dispose();
}
if (_currentBottomSheet != null) {
_currentBottomSheet._widget.animationController?.dispose();
_currentBottomSheet!._widget.animationController?.dispose();
}
_floatingActionButtonMoveController.dispose();
_floatingActionButtonVisibilityController.dispose();
......@@ -2243,16 +2241,16 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin {
void _addIfNonNull(
List<LayoutId> children,
Widget child,
Widget? child,
Object childId, {
@required bool removeLeftPadding,
@required bool removeTopPadding,
@required bool removeRightPadding,
@required bool removeBottomPadding,
required bool removeLeftPadding,
required bool removeTopPadding,
required bool removeRightPadding,
required bool removeBottomPadding,
bool removeBottomInset = false,
bool maintainBottomViewPadding = false,
}) {
MediaQueryData data = MediaQuery.of(context).removePadding(
MediaQueryData data = MediaQuery.of(context)!.removePadding(
removeLeft: removeLeftPadding,
removeTop: removeTopPadding,
removeRight: removeRightPadding,
......@@ -2285,7 +2283,7 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin {
DrawerController(
key: _endDrawerKey,
alignment: DrawerAlignment.end,
child: widget.endDrawer,
child: widget.endDrawer!,
drawerCallback: _endDrawerOpenedCallback,
dragStartBehavior: widget.drawerDragStartBehavior,
scrimColor: widget.drawerScrimColor,
......@@ -2310,7 +2308,7 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin {
DrawerController(
key: _drawerKey,
alignment: DrawerAlignment.start,
child: widget.drawer,
child: widget.drawer!,
drawerCallback: _drawerOpenedCallback,
dragStartBehavior: widget.drawerDragStartBehavior,
scrimColor: widget.drawerScrimColor,
......@@ -2348,21 +2346,21 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin {
Widget build(BuildContext context) {
assert(debugCheckHasMediaQuery(context));
assert(debugCheckHasDirectionality(context));
final MediaQueryData mediaQuery = MediaQuery.of(context);
final ThemeData themeData = Theme.of(context);
final TextDirection textDirection = Directionality.of(context);
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);
final ModalRoute<dynamic>? route = ModalRoute.of(context);
if (route == null || route.isCurrent) {
if (_snackBarController.isCompleted && _snackBarTimer == null) {
if (_snackBarController!.isCompleted && _snackBarTimer == null) {
final SnackBar snackBar = _snackBars.first._widget;
_snackBarTimer = Timer(snackBar.duration, () {
assert(_snackBarController.status == AnimationStatus.forward ||
_snackBarController.status == AnimationStatus.completed);
assert(_snackBarController!.status == AnimationStatus.forward ||
_snackBarController!.status == AnimationStatus.completed);
// Look up MediaQuery again in case the setting changed.
final MediaQueryData mediaQuery = MediaQuery.of(context);
final MediaQueryData mediaQuery = MediaQuery.of(context)!;
if (mediaQuery.accessibleNavigation && snackBar.action != null)
return;
hideCurrentSnackBar(reason: SnackBarClosedReason.timeout);
......@@ -2380,7 +2378,7 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin {
widget.body == null ? null : _BodyBuilder(
extendBody: widget.extendBody,
extendBodyBehindAppBar: widget.extendBodyBehindAppBar,
body: widget.body,
body: widget.body!,
),
_ScaffoldSlot.body,
removeLeftPadding: false,
......@@ -2406,15 +2404,15 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin {
if (widget.appBar != null) {
final double topPadding = widget.primary ? mediaQuery.padding.top : 0.0;
_appBarMaxHeight = widget.appBar.preferredSize.height + topPadding;
assert(_appBarMaxHeight >= 0.0 && _appBarMaxHeight.isFinite);
_appBarMaxHeight = widget.appBar!.preferredSize.height + topPadding;
assert(_appBarMaxHeight! >= 0.0 && _appBarMaxHeight!.isFinite);
_addIfNonNull(
children,
ConstrainedBox(
constraints: BoxConstraints(maxHeight: _appBarMaxHeight),
constraints: BoxConstraints(maxHeight: _appBarMaxHeight!),
child: FlexibleSpaceBar.createSettings(
currentExtent: _appBarMaxHeight,
child: widget.appBar,
currentExtent: _appBarMaxHeight!,
child: widget.appBar!,
),
),
_ScaffoldSlot.appBar,
......@@ -2426,7 +2424,7 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin {
}
bool isSnackBarFloating = false;
double snackBarWidth;
double? snackBarWidth;
if (_snackBars.isNotEmpty) {
final SnackBarBehavior snackBarBehavior = _snackBars.first._widget.behavior
?? themeData.snackBarTheme.behavior
......@@ -2458,7 +2456,7 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin {
child: SafeArea(
top: false,
child: ButtonBar(
children: widget.persistentFooterButtons,
children: widget.persistentFooterButtons!,
),
),
),
......@@ -2489,7 +2487,7 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin {
alignment: Alignment.bottomCenter,
children: <Widget>[
..._dismissedBottomSheets,
if (_currentBottomSheet != null) _currentBottomSheet._widget,
if (_currentBottomSheet != null) _currentBottomSheet!._widget,
],
);
_addIfNonNull(
......@@ -2509,7 +2507,7 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin {
child: widget.floatingActionButton,
fabMoveAnimation: _floatingActionButtonMoveController,
fabMotionAnimator: _floatingActionButtonAnimator,
geometryNotifier: _geometryNotifier,
geometryNotifier: _geometryNotifier!,
currentController: _floatingActionButtonVisibilityController,
),
_ScaffoldSlot.floatingActionButton,
......@@ -2573,7 +2571,7 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin {
controller: _primaryScrollController,
child: Material(
color: widget.backgroundColor ?? themeData.scaffoldBackgroundColor,
child: AnimatedBuilder(animation: _floatingActionButtonMoveController, builder: (BuildContext context, Widget child) {
child: AnimatedBuilder(animation: _floatingActionButtonMoveController, builder: (BuildContext context, Widget? child) {
return CustomMultiChildLayout(
children: children,
delegate: _ScaffoldLayout(
......@@ -2581,11 +2579,11 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin {
extendBodyBehindAppBar: widget.extendBodyBehindAppBar,
minInsets: minInsets,
minViewPadding: minViewPadding,
currentFloatingActionButtonLocation: _floatingActionButtonLocation,
currentFloatingActionButtonLocation: _floatingActionButtonLocation!,
floatingActionButtonMoveAnimationProgress: _floatingActionButtonMoveController.value,
floatingActionButtonMotionAnimator: _floatingActionButtonAnimator,
geometryNotifier: _geometryNotifier,
previousFloatingActionButtonLocation: _previousFloatingActionButtonLocation,
geometryNotifier: _geometryNotifier!,
previousFloatingActionButtonLocation: _previousFloatingActionButtonLocation!,
textDirection: textDirection,
isSnackBarFloating: isSnackBarFloating,
snackBarWidth: snackBarWidth,
......@@ -2613,7 +2611,7 @@ class ScaffoldFeatureController<T extends Widget, U> {
final VoidCallback close;
/// Mark the feature (e.g., bottom sheet or snack bar) as needing to rebuild.
final StateSetter setState;
final StateSetter? setState;
}
// TODO(guidezpl): Look into making this public. A copy of this class is in
......@@ -2665,7 +2663,7 @@ class _BottomSheetSuspendedCurve extends ParametricCurve<double> {
final double curveProgress = (t - startingPoint) / (1 - startingPoint);
final double transformed = curve.transform(curveProgress);
return lerpDouble(startingPoint, 1, transformed);
return lerpDouble(startingPoint, 1, transformed)!;
}
@override
......@@ -2676,12 +2674,12 @@ class _BottomSheetSuspendedCurve extends ParametricCurve<double> {
class _StandardBottomSheet extends StatefulWidget {
const _StandardBottomSheet({
Key key,
this.animationController,
Key? key,
required this.animationController,
this.enableDrag = true,
this.onClosing,
this.onDismissed,
this.builder,
required this.onClosing,
required this.onDismissed,
required this.builder,
this.isPersistent = false,
this.backgroundColor,
this.elevation,
......@@ -2689,16 +2687,16 @@ class _StandardBottomSheet extends StatefulWidget {
this.clipBehavior,
}) : super(key: key);
final AnimationController animationController; // we control it, but it must be disposed by whoever created it.
final AnimationController? animationController; // we control it, but it must be disposed by whoever created it.
final bool enableDrag;
final VoidCallback onClosing;
final VoidCallback onDismissed;
final VoidCallback? onClosing;
final VoidCallback? onDismissed;
final WidgetBuilder builder;
final bool isPersistent;
final Color backgroundColor;
final double elevation;
final ShapeBorder shape;
final Clip clipBehavior;
final Color? backgroundColor;
final double? elevation;
final ShapeBorder? shape;
final Clip? clipBehavior;
@override
_StandardBottomSheetState createState() => _StandardBottomSheetState();
......@@ -2711,9 +2709,9 @@ class _StandardBottomSheetState extends State<_StandardBottomSheet> {
void initState() {
super.initState();
assert(widget.animationController != null);
assert(widget.animationController.status == AnimationStatus.forward
|| widget.animationController.status == AnimationStatus.completed);
widget.animationController.addStatusListener(_handleStatusChange);
assert(widget.animationController!.status == AnimationStatus.forward
|| widget.animationController!.status == AnimationStatus.completed);
widget.animationController!.addStatusListener(_handleStatusChange);
}
@override
......@@ -2722,13 +2720,10 @@ class _StandardBottomSheetState extends State<_StandardBottomSheet> {
assert(widget.animationController == oldWidget.animationController);
}
Future<void> close() {
Future<void> close() async {
assert(widget.animationController != null);
widget.animationController.reverse();
if (widget.onClosing != null) {
widget.onClosing();
}
return null;
widget.animationController!.reverse();
widget.onClosing?.call();
}
void _handleDragStart(DragStartDetails details) {
......@@ -2736,23 +2731,23 @@ class _StandardBottomSheetState extends State<_StandardBottomSheet> {
animationCurve = Curves.linear;
}
void _handleDragEnd(DragEndDetails details, { bool isClosing }) {
void _handleDragEnd(DragEndDetails details, { bool? isClosing }) {
// Allow the bottom sheet to animate smoothly from its current position.
animationCurve = _BottomSheetSuspendedCurve(
widget.animationController.value,
widget.animationController!.value,
curve: _standardBottomSheetCurve,
);
}
void _handleStatusChange(AnimationStatus status) {
if (status == AnimationStatus.dismissed && widget.onDismissed != null) {
widget.onDismissed();
if (status == AnimationStatus.dismissed) {
widget.onDismissed?.call();
}
}
bool extentChanged(DraggableScrollableNotification notification) {
final double extentRemaining = 1.0 - notification.extent;
final ScaffoldState scaffold = Scaffold.of(context);
final ScaffoldState scaffold = Scaffold.of(context)!;
if (extentRemaining < _kBottomSheetDominatesPercentage) {
scaffold._floatingActionButtonVisibilityValue = extentRemaining * _kBottomSheetDominatesPercentage * 10;
scaffold.showBodyScrim(true, math.max(
......@@ -2785,11 +2780,11 @@ class _StandardBottomSheetState extends State<_StandardBottomSheet> {
Widget build(BuildContext context) {
if (widget.animationController != null) {
return AnimatedBuilder(
animation: widget.animationController,
builder: (BuildContext context, Widget child) {
animation: widget.animationController!,
builder: (BuildContext context, Widget? child) {
return Align(
alignment: AlignmentDirectional.topStart,
heightFactor: animationCurve.transform(widget.animationController.value),
heightFactor: animationCurve.transform(widget.animationController!.value),
child: child,
);
},
......@@ -2799,7 +2794,7 @@ class _StandardBottomSheetState extends State<_StandardBottomSheet> {
enableDrag: widget.enableDrag,
onDragStart: _handleDragStart,
onDragEnd: _handleDragEnd,
onClosing: widget.onClosing,
onClosing: widget.onClosing!,
builder: widget.builder,
backgroundColor: widget.backgroundColor,
elevation: widget.elevation,
......@@ -2812,7 +2807,7 @@ class _StandardBottomSheetState extends State<_StandardBottomSheet> {
return _wrapBottomSheet(
BottomSheet(
onClosing: widget.onClosing,
onClosing: widget.onClosing!,
builder: widget.builder,
backgroundColor: widget.backgroundColor,
),
......@@ -2842,15 +2837,15 @@ class PersistentBottomSheetController<T> extends ScaffoldFeatureController<_Stan
class _ScaffoldScope extends InheritedWidget {
const _ScaffoldScope({
Key key,
@required this.hasDrawer,
@required this.geometryNotifier,
@required Widget child,
Key? key,
required this.hasDrawer,
required this.geometryNotifier,
required Widget child,
}) : assert(hasDrawer != null),
super(key: key, child: child);
final bool hasDrawer;
final _ScaffoldGeometryNotifier geometryNotifier;
final _ScaffoldGeometryNotifier? geometryNotifier;
@override
bool updateShouldNotify(_ScaffoldScope oldWidget) {
......
......@@ -30,7 +30,7 @@ void main() {
expect(themeData.showUnselectedLabels, null);
expect(themeData.type, null);
const BottomNavigationBarTheme theme = BottomNavigationBarTheme(data: BottomNavigationBarThemeData());
const BottomNavigationBarTheme theme = BottomNavigationBarTheme(data: BottomNavigationBarThemeData(), child: SizedBox());
expect(theme.data.backgroundColor, null);
expect(theme.data.elevation, null);
expect(theme.data.selectedIconTheme, null);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment