Unverified Commit 19078b1a authored by Alexandre Ardhuin's avatar Alexandre Ardhuin Committed by GitHub

migrate cupertino to nullsafety (#66493)

parent 48ce83a8
...@@ -2,8 +2,6 @@ ...@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// @dart = 2.8
/// Flutter widgets implementing the current iOS design language. /// Flutter widgets implementing the current iOS design language.
/// ///
/// To use, import `package:flutter/cupertino.dart`. /// To use, import `package:flutter/cupertino.dart`.
......
...@@ -2,8 +2,6 @@ ...@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// @dart = 2.8
import 'dart:math' as math; import 'dart:math' as math;
import 'dart:ui' show ImageFilter; import 'dart:ui' show ImageFilter;
...@@ -58,7 +56,7 @@ const _HeroTag _defaultHeroTag = _HeroTag(null); ...@@ -58,7 +56,7 @@ const _HeroTag _defaultHeroTag = _HeroTag(null);
class _HeroTag { class _HeroTag {
const _HeroTag(this.navigator); const _HeroTag(this.navigator);
final NavigatorState navigator; final NavigatorState? navigator;
// Let the Hero tag be described in tree dumps. // Let the Hero tag be described in tree dumps.
@override @override
...@@ -88,10 +86,10 @@ class _HeroTag { ...@@ -88,10 +86,10 @@ class _HeroTag {
/// When `updateSystemUiOverlay` is true, the nav bar will update the OS /// When `updateSystemUiOverlay` is true, the nav bar will update the OS
/// status bar's color theme based on the background color of the nav bar. /// status bar's color theme based on the background color of the nav bar.
Widget _wrapWithBackground({ Widget _wrapWithBackground({
Border border, Border? border,
Color backgroundColor, required Color backgroundColor,
Brightness brightness, Brightness? brightness,
Widget child, required Widget child,
bool updateSystemUiOverlay = true, bool updateSystemUiOverlay = true,
}) { }) {
Widget result = child; Widget result = child;
...@@ -137,7 +135,7 @@ Widget _wrapWithBackground({ ...@@ -137,7 +135,7 @@ Widget _wrapWithBackground({
// `actionsForegroundColor`. CupertinoThemes can be used to support these // `actionsForegroundColor`. CupertinoThemes can be used to support these
// scenarios now. To support `actionsForegroundColor`, the nav bar rewraps // scenarios now. To support `actionsForegroundColor`, the nav bar rewraps
// its children with a CupertinoTheme. // its children with a CupertinoTheme.
Widget _wrapActiveColor(Color color, BuildContext context, Widget child) { Widget _wrapActiveColor(Color? color, BuildContext context, Widget child) {
if (color == null) { if (color == null) {
return child; return child;
} }
...@@ -150,7 +148,7 @@ Widget _wrapActiveColor(Color color, BuildContext context, Widget child) { ...@@ -150,7 +148,7 @@ Widget _wrapActiveColor(Color color, BuildContext context, Widget child) {
// Whether the current route supports nav bar hero transitions from or to. // Whether the current route supports nav bar hero transitions from or to.
bool _isTransitionable(BuildContext context) { bool _isTransitionable(BuildContext context) {
final ModalRoute<dynamic> route = ModalRoute.of(context); final ModalRoute<dynamic>? route = ModalRoute.of(context);
// Fullscreen dialogs never transitions their nav bar with other push-style // Fullscreen dialogs never transitions their nav bar with other push-style
// pages' nav bars or with other fullscreen dialog pages on the way in or on // pages' nav bars or with other fullscreen dialog pages on the way in or on
...@@ -209,7 +207,7 @@ bool _isTransitionable(BuildContext context) { ...@@ -209,7 +207,7 @@ bool _isTransitionable(BuildContext context) {
class CupertinoNavigationBar extends StatefulWidget implements ObstructingPreferredSizeWidget { class CupertinoNavigationBar extends StatefulWidget implements ObstructingPreferredSizeWidget {
/// Creates a navigation bar in the iOS style. /// Creates a navigation bar in the iOS style.
const CupertinoNavigationBar({ const CupertinoNavigationBar({
Key key, Key? key,
this.leading, this.leading,
this.automaticallyImplyLeading = true, this.automaticallyImplyLeading = true,
this.automaticallyImplyMiddle = true, this.automaticallyImplyMiddle = true,
...@@ -245,7 +243,7 @@ class CupertinoNavigationBar extends StatefulWidget implements ObstructingPrefer ...@@ -245,7 +243,7 @@ class CupertinoNavigationBar extends StatefulWidget implements ObstructingPrefer
/// If null and [automaticallyImplyLeading] is true, an appropriate button /// If null and [automaticallyImplyLeading] is true, an appropriate button
/// will be automatically created. /// will be automatically created.
/// {@endtemplate} /// {@endtemplate}
final Widget leading; final Widget? leading;
/// {@template flutter.cupertino.navBar.automaticallyImplyLeading} /// {@template flutter.cupertino.navBar.automaticallyImplyLeading}
/// Controls whether we should try to imply the leading widget if null. /// Controls whether we should try to imply the leading widget if null.
...@@ -286,7 +284,7 @@ class CupertinoNavigationBar extends StatefulWidget implements ObstructingPrefer ...@@ -286,7 +284,7 @@ class CupertinoNavigationBar extends StatefulWidget implements ObstructingPrefer
/// Has no effect when [leading] is not null or if [automaticallyImplyLeading] /// Has no effect when [leading] is not null or if [automaticallyImplyLeading]
/// is false. /// is false.
/// {@endtemplate} /// {@endtemplate}
final String previousPageTitle; final String? previousPageTitle;
/// Widget to place in the middle of the navigation bar. Normally a title or /// Widget to place in the middle of the navigation bar. Normally a title or
/// a segmented control. /// a segmented control.
...@@ -294,13 +292,13 @@ class CupertinoNavigationBar extends StatefulWidget implements ObstructingPrefer ...@@ -294,13 +292,13 @@ class CupertinoNavigationBar extends StatefulWidget implements ObstructingPrefer
/// If null and [automaticallyImplyMiddle] is true, an appropriate [Text] /// If null and [automaticallyImplyMiddle] is true, an appropriate [Text]
/// title will be created if the current route is a [CupertinoPageRoute] and /// title will be created if the current route is a [CupertinoPageRoute] and
/// has a `title`. /// has a `title`.
final Widget middle; final Widget? middle;
/// {@template flutter.cupertino.navBar.trailing} /// {@template flutter.cupertino.navBar.trailing}
/// Widget to place at the end of the navigation bar. Normally additional actions /// Widget to place at the end of the navigation bar. Normally additional actions
/// taken on the page such as a search or edit function. /// taken on the page such as a search or edit function.
/// {@endtemplate} /// {@endtemplate}
final Widget trailing; final Widget? trailing;
// TODO(xster): https://github.com/flutter/flutter/issues/10469 implement // TODO(xster): https://github.com/flutter/flutter/issues/10469 implement
// support for double row navigation bars. // support for double row navigation bars.
...@@ -312,7 +310,7 @@ class CupertinoNavigationBar extends StatefulWidget implements ObstructingPrefer ...@@ -312,7 +310,7 @@ class CupertinoNavigationBar extends StatefulWidget implements ObstructingPrefer
/// ///
/// Defaults to [CupertinoTheme]'s `barBackgroundColor` if null. /// Defaults to [CupertinoTheme]'s `barBackgroundColor` if null.
/// {@endtemplate} /// {@endtemplate}
final Color backgroundColor; final Color? backgroundColor;
/// {@template flutter.cupertino.navBar.brightness} /// {@template flutter.cupertino.navBar.brightness}
/// The brightness of the specified [backgroundColor]. /// The brightness of the specified [backgroundColor].
...@@ -324,7 +322,7 @@ class CupertinoNavigationBar extends StatefulWidget implements ObstructingPrefer ...@@ -324,7 +322,7 @@ class CupertinoNavigationBar extends StatefulWidget implements ObstructingPrefer
/// If set to null, the value of the property will be inferred from the relative /// If set to null, the value of the property will be inferred from the relative
/// luminance of [backgroundColor]. /// luminance of [backgroundColor].
/// {@endtemplate} /// {@endtemplate}
final Brightness brightness; final Brightness? brightness;
/// {@template flutter.cupertino.navBar.padding} /// {@template flutter.cupertino.navBar.padding}
/// Padding for the contents of the navigation bar. /// Padding for the contents of the navigation bar.
...@@ -339,7 +337,7 @@ class CupertinoNavigationBar extends StatefulWidget implements ObstructingPrefer ...@@ -339,7 +337,7 @@ class CupertinoNavigationBar extends StatefulWidget implements ObstructingPrefer
/// ///
/// Vertical padding won't change the height of the nav bar. /// Vertical padding won't change the height of the nav bar.
/// {@endtemplate} /// {@endtemplate}
final EdgeInsetsDirectional padding; final EdgeInsetsDirectional? padding;
/// {@template flutter.cupertino.navBar.border} /// {@template flutter.cupertino.navBar.border}
/// The border of the navigation bar. By default renders a single pixel bottom border side. /// The border of the navigation bar. By default renders a single pixel bottom border side.
...@@ -361,7 +359,7 @@ class CupertinoNavigationBar extends StatefulWidget implements ObstructingPrefer ...@@ -361,7 +359,7 @@ class CupertinoNavigationBar extends StatefulWidget implements ObstructingPrefer
'Use CupertinoTheme and primaryColor to propagate color. ' 'Use CupertinoTheme and primaryColor to propagate color. '
'This feature was deprecated after v1.1.2.' 'This feature was deprecated after v1.1.2.'
) )
final Color actionsForegroundColor; final Color? actionsForegroundColor;
/// {@template flutter.cupertino.navBar.transitionBetweenRoutes} /// {@template flutter.cupertino.navBar.transitionBetweenRoutes}
/// Whether to transition between navigation bars. /// Whether to transition between navigation bars.
...@@ -422,7 +420,7 @@ class CupertinoNavigationBar extends StatefulWidget implements ObstructingPrefer ...@@ -422,7 +420,7 @@ class CupertinoNavigationBar extends StatefulWidget implements ObstructingPrefer
// don't change when rebuilding the nav bar, causing the sub-components to // don't change when rebuilding the nav bar, causing the sub-components to
// lose their own states. // lose their own states.
class _CupertinoNavigationBarState extends State<CupertinoNavigationBar> { class _CupertinoNavigationBarState extends State<CupertinoNavigationBar> {
_NavigationBarStaticComponentsKeys keys; late _NavigationBarStaticComponentsKeys keys;
@override @override
void initState() { void initState() {
...@@ -462,7 +460,7 @@ class _CupertinoNavigationBarState extends State<CupertinoNavigationBar> { ...@@ -462,7 +460,7 @@ class _CupertinoNavigationBarState extends State<CupertinoNavigationBar> {
), ),
); );
final Color actionsForegroundColor = CupertinoDynamicColor.resolve( final Color? actionsForegroundColor = CupertinoDynamicColor.resolve(
widget.actionsForegroundColor, widget.actionsForegroundColor,
context, context,
); );
...@@ -563,7 +561,7 @@ class CupertinoSliverNavigationBar extends StatefulWidget { ...@@ -563,7 +561,7 @@ class CupertinoSliverNavigationBar extends StatefulWidget {
/// ///
/// The [largeTitle] argument is required and must not be null. /// The [largeTitle] argument is required and must not be null.
const CupertinoSliverNavigationBar({ const CupertinoSliverNavigationBar({
Key key, Key? key,
this.largeTitle, this.largeTitle,
this.leading, this.leading,
this.automaticallyImplyLeading = true, this.automaticallyImplyLeading = true,
...@@ -609,12 +607,12 @@ class CupertinoSliverNavigationBar extends StatefulWidget { ...@@ -609,12 +607,12 @@ class CupertinoSliverNavigationBar extends StatefulWidget {
/// ///
/// This parameter must either be non-null or the route must have a title /// This parameter must either be non-null or the route must have a title
/// ([CupertinoPageRoute.title]) and [automaticallyImplyTitle] must be true. /// ([CupertinoPageRoute.title]) and [automaticallyImplyTitle] must be true.
final Widget largeTitle; final Widget? largeTitle;
/// {@macro flutter.cupertino.navBar.leading} /// {@macro flutter.cupertino.navBar.leading}
/// ///
/// This widget is visible in both collapsed and expanded states. /// This widget is visible in both collapsed and expanded states.
final Widget leading; final Widget? leading;
/// {@macro flutter.cupertino.navBar.automaticallyImplyLeading} /// {@macro flutter.cupertino.navBar.automaticallyImplyLeading}
final bool automaticallyImplyLeading; final bool automaticallyImplyLeading;
...@@ -629,7 +627,7 @@ class CupertinoSliverNavigationBar extends StatefulWidget { ...@@ -629,7 +627,7 @@ class CupertinoSliverNavigationBar extends StatefulWidget {
final bool automaticallyImplyTitle; final bool automaticallyImplyTitle;
/// {@macro flutter.cupertino.navBar.previousPageTitle} /// {@macro flutter.cupertino.navBar.previousPageTitle}
final String previousPageTitle; final String? previousPageTitle;
/// A widget to place in the middle of the static navigation bar instead of /// A widget to place in the middle of the static navigation bar instead of
/// the [largeTitle]. /// the [largeTitle].
...@@ -637,21 +635,21 @@ class CupertinoSliverNavigationBar extends StatefulWidget { ...@@ -637,21 +635,21 @@ class CupertinoSliverNavigationBar extends StatefulWidget {
/// This widget is visible in both collapsed and expanded states. The text /// This widget is visible in both collapsed and expanded states. The text
/// supplied in [largeTitle] will no longer appear in collapsed state if a /// supplied in [largeTitle] will no longer appear in collapsed state if a
/// [middle] widget is provided. /// [middle] widget is provided.
final Widget middle; final Widget? middle;
/// {@macro flutter.cupertino.navBar.trailing} /// {@macro flutter.cupertino.navBar.trailing}
/// ///
/// This widget is visible in both collapsed and expanded states. /// This widget is visible in both collapsed and expanded states.
final Widget trailing; final Widget? trailing;
/// {@macro flutter.cupertino.navBar.backgroundColor} /// {@macro flutter.cupertino.navBar.backgroundColor}
final Color backgroundColor; final Color? backgroundColor;
/// {@macro flutter.cupertino.navBar.brightness} /// {@macro flutter.cupertino.navBar.brightness}
final Brightness brightness; final Brightness? brightness;
/// {@macro flutter.cupertino.navBar.padding} /// {@macro flutter.cupertino.navBar.padding}
final EdgeInsetsDirectional padding; final EdgeInsetsDirectional? padding;
/// {@macro flutter.cupertino.navBar.border} /// {@macro flutter.cupertino.navBar.border}
final Border border; final Border border;
...@@ -664,7 +662,7 @@ class CupertinoSliverNavigationBar extends StatefulWidget { ...@@ -664,7 +662,7 @@ class CupertinoSliverNavigationBar extends StatefulWidget {
'Use CupertinoTheme and primaryColor to propagate color. ' 'Use CupertinoTheme and primaryColor to propagate color. '
'This feature was deprecated after v1.1.2.' 'This feature was deprecated after v1.1.2.'
) )
final Color actionsForegroundColor; final Color? actionsForegroundColor;
/// {@macro flutter.cupertino.navBar.transitionBetweenRoutes} /// {@macro flutter.cupertino.navBar.transitionBetweenRoutes}
final bool transitionBetweenRoutes; final bool transitionBetweenRoutes;
...@@ -673,7 +671,7 @@ class CupertinoSliverNavigationBar extends StatefulWidget { ...@@ -673,7 +671,7 @@ class CupertinoSliverNavigationBar extends StatefulWidget {
final Object heroTag; final Object heroTag;
/// True if the navigation bar's background color has no transparency. /// True if the navigation bar's background color has no transparency.
bool get opaque => backgroundColor.alpha == 0xFF; bool get opaque => backgroundColor?.alpha == 0xFF;
@override @override
_CupertinoSliverNavigationBarState createState() => _CupertinoSliverNavigationBarState(); _CupertinoSliverNavigationBarState createState() => _CupertinoSliverNavigationBarState();
...@@ -683,7 +681,7 @@ class CupertinoSliverNavigationBar extends StatefulWidget { ...@@ -683,7 +681,7 @@ class CupertinoSliverNavigationBar extends StatefulWidget {
// don't change when rebuilding the nav bar, causing the sub-components to // don't change when rebuilding the nav bar, causing the sub-components to
// lose their own states. // lose their own states.
class _CupertinoSliverNavigationBarState extends State<CupertinoSliverNavigationBar> { class _CupertinoSliverNavigationBarState extends State<CupertinoSliverNavigationBar> {
_NavigationBarStaticComponentsKeys keys; late _NavigationBarStaticComponentsKeys keys;
@override @override
void initState() { void initState() {
...@@ -716,7 +714,7 @@ class _CupertinoSliverNavigationBarState extends State<CupertinoSliverNavigation ...@@ -716,7 +714,7 @@ class _CupertinoSliverNavigationBarState extends State<CupertinoSliverNavigation
actionsForegroundColor, actionsForegroundColor,
context, context,
MediaQuery( MediaQuery(
data: MediaQuery.of(context).copyWith(textScaleFactor: 1), data: MediaQuery.of(context)!.copyWith(textScaleFactor: 1),
child: SliverPersistentHeader( child: SliverPersistentHeader(
pinned: true, // iOS navigation bars are always pinned. pinned: true, // iOS navigation bars are always pinned.
delegate: _LargeTitleNavigationBarSliverDelegate( delegate: _LargeTitleNavigationBarSliverDelegate(
...@@ -730,7 +728,7 @@ class _CupertinoSliverNavigationBarState extends State<CupertinoSliverNavigation ...@@ -730,7 +728,7 @@ class _CupertinoSliverNavigationBarState extends State<CupertinoSliverNavigation
actionsForegroundColor: actionsForegroundColor, actionsForegroundColor: actionsForegroundColor,
transitionBetweenRoutes: widget.transitionBetweenRoutes, transitionBetweenRoutes: widget.transitionBetweenRoutes,
heroTag: widget.heroTag, heroTag: widget.heroTag,
persistentHeight: _kNavBarPersistentHeight + MediaQuery.of(context).padding.top, persistentHeight: _kNavBarPersistentHeight + MediaQuery.of(context)!.padding.top,
alwaysShowMiddle: widget.middle != null, alwaysShowMiddle: widget.middle != null,
), ),
), ),
...@@ -742,29 +740,29 @@ class _CupertinoSliverNavigationBarState extends State<CupertinoSliverNavigation ...@@ -742,29 +740,29 @@ class _CupertinoSliverNavigationBarState extends State<CupertinoSliverNavigation
class _LargeTitleNavigationBarSliverDelegate class _LargeTitleNavigationBarSliverDelegate
extends SliverPersistentHeaderDelegate with DiagnosticableTreeMixin { extends SliverPersistentHeaderDelegate with DiagnosticableTreeMixin {
_LargeTitleNavigationBarSliverDelegate({ _LargeTitleNavigationBarSliverDelegate({
@required this.keys, required this.keys,
@required this.components, required this.components,
@required this.userMiddle, required this.userMiddle,
@required this.backgroundColor, required this.backgroundColor,
@required this.brightness, required this.brightness,
@required this.border, required this.border,
@required this.padding, required this.padding,
@required this.actionsForegroundColor, required this.actionsForegroundColor,
@required this.transitionBetweenRoutes, required this.transitionBetweenRoutes,
@required this.heroTag, required this.heroTag,
@required this.persistentHeight, required this.persistentHeight,
@required this.alwaysShowMiddle, required this.alwaysShowMiddle,
}) : assert(persistentHeight != null), }) : assert(persistentHeight != null),
assert(alwaysShowMiddle != null), assert(alwaysShowMiddle != null),
assert(transitionBetweenRoutes != null); assert(transitionBetweenRoutes != null);
final _NavigationBarStaticComponentsKeys keys; final _NavigationBarStaticComponentsKeys keys;
final _NavigationBarStaticComponents components; final _NavigationBarStaticComponents components;
final Widget userMiddle; final Widget? userMiddle;
final Color backgroundColor; final Color backgroundColor;
final Brightness brightness; final Brightness? brightness;
final Border border; final Border? border;
final EdgeInsetsDirectional padding; final EdgeInsetsDirectional? padding;
final Color actionsForegroundColor; final Color actionsForegroundColor;
final bool transitionBetweenRoutes; final bool transitionBetweenRoutes;
final Object heroTag; final Object heroTag;
...@@ -792,7 +790,7 @@ class _LargeTitleNavigationBarSliverDelegate ...@@ -792,7 +790,7 @@ class _LargeTitleNavigationBarSliverDelegate
final Widget navBar = _wrapWithBackground( final Widget navBar = _wrapWithBackground(
border: border, border: border,
backgroundColor: CupertinoDynamicColor.resolve(backgroundColor, context), backgroundColor: CupertinoDynamicColor.resolve(backgroundColor, context)!,
brightness: brightness, brightness: brightness,
child: DefaultTextStyle( child: DefaultTextStyle(
style: CupertinoTheme.of(context).textTheme.textStyle, style: CupertinoTheme.of(context).textTheme.textStyle,
...@@ -829,7 +827,7 @@ class _LargeTitleNavigationBarSliverDelegate ...@@ -829,7 +827,7 @@ class _LargeTitleNavigationBarSliverDelegate
style: CupertinoTheme.of(context).textTheme.navLargeTitleTextStyle, style: CupertinoTheme.of(context).textTheme.navLargeTitleTextStyle,
maxLines: 1, maxLines: 1,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
child: components.largeTitle, child: components.largeTitle!,
), ),
), ),
), ),
...@@ -900,22 +898,22 @@ class _LargeTitleNavigationBarSliverDelegate ...@@ -900,22 +898,22 @@ class _LargeTitleNavigationBarSliverDelegate
/// doesn't scroll. /// doesn't scroll.
class _PersistentNavigationBar extends StatelessWidget { class _PersistentNavigationBar extends StatelessWidget {
const _PersistentNavigationBar({ const _PersistentNavigationBar({
Key key, Key? key,
this.components, required this.components,
this.padding, this.padding,
this.middleVisible, this.middleVisible,
}) : super(key: key); }) : super(key: key);
final _NavigationBarStaticComponents components; final _NavigationBarStaticComponents components;
final EdgeInsetsDirectional padding; final EdgeInsetsDirectional? padding;
/// Whether the middle widget has a visible animated opacity. A null value /// Whether the middle widget has a visible animated opacity. A null value
/// means the middle opacity will not be animated. /// means the middle opacity will not be animated.
final bool middleVisible; final bool? middleVisible;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
Widget middle = components.middle; Widget? middle = components.middle;
if (middle != null) { if (middle != null) {
middle = DefaultTextStyle( middle = DefaultTextStyle(
...@@ -927,15 +925,15 @@ class _PersistentNavigationBar extends StatelessWidget { ...@@ -927,15 +925,15 @@ class _PersistentNavigationBar extends StatelessWidget {
middle = middleVisible == null middle = middleVisible == null
? middle ? middle
: AnimatedOpacity( : AnimatedOpacity(
opacity: middleVisible ? 1.0 : 0.0, opacity: middleVisible! ? 1.0 : 0.0,
duration: _kNavBarTitleFadeDuration, duration: _kNavBarTitleFadeDuration,
child: middle, child: middle,
); );
} }
Widget leading = components.leading; Widget? leading = components.leading;
final Widget backChevron = components.backChevron; final Widget? backChevron = components.backChevron;
final Widget backLabel = components.backLabel; final Widget? backLabel = components.backLabel;
if (leading == null && backChevron != null && backLabel != null) { if (leading == null && backChevron != null && backLabel != null) {
leading = CupertinoNavigationBarBackButton._assemble( leading = CupertinoNavigationBarBackButton._assemble(
...@@ -955,15 +953,15 @@ class _PersistentNavigationBar extends StatelessWidget { ...@@ -955,15 +953,15 @@ class _PersistentNavigationBar extends StatelessWidget {
if (padding != null) { if (padding != null) {
paddedToolbar = Padding( paddedToolbar = Padding(
padding: EdgeInsets.only( padding: EdgeInsets.only(
top: padding.top, top: padding!.top,
bottom: padding.bottom, bottom: padding!.bottom,
), ),
child: paddedToolbar, child: paddedToolbar,
); );
} }
return SizedBox( return SizedBox(
height: _kNavBarPersistentHeight + MediaQuery.of(context).padding.top, height: _kNavBarPersistentHeight + MediaQuery.of(context)!.padding.top,
child: SafeArea( child: SafeArea(
bottom: false, bottom: false,
child: paddedToolbar, child: paddedToolbar,
...@@ -1005,17 +1003,17 @@ class _NavigationBarStaticComponentsKeys { ...@@ -1005,17 +1003,17 @@ class _NavigationBarStaticComponentsKeys {
@immutable @immutable
class _NavigationBarStaticComponents { class _NavigationBarStaticComponents {
_NavigationBarStaticComponents({ _NavigationBarStaticComponents({
@required _NavigationBarStaticComponentsKeys keys, required _NavigationBarStaticComponentsKeys keys,
@required ModalRoute<dynamic> route, required ModalRoute<dynamic>? route,
@required Widget userLeading, required Widget? userLeading,
@required bool automaticallyImplyLeading, required bool automaticallyImplyLeading,
@required bool automaticallyImplyTitle, required bool automaticallyImplyTitle,
@required String previousPageTitle, required String? previousPageTitle,
@required Widget userMiddle, required Widget? userMiddle,
@required Widget userTrailing, required Widget? userTrailing,
@required Widget userLargeTitle, required Widget? userLargeTitle,
@required EdgeInsetsDirectional padding, required EdgeInsetsDirectional? padding,
@required bool large, required bool large,
}) : leading = createLeading( }) : leading = createLeading(
leadingKey: keys.leadingKey, leadingKey: keys.leadingKey,
userLeading: userLeading, userLeading: userLeading,
...@@ -1057,29 +1055,29 @@ class _NavigationBarStaticComponents { ...@@ -1057,29 +1055,29 @@ class _NavigationBarStaticComponents {
large: large, large: large,
); );
static Widget _derivedTitle({ static Widget? _derivedTitle({
bool automaticallyImplyTitle, required bool automaticallyImplyTitle,
ModalRoute<dynamic> currentRoute, ModalRoute<dynamic>? currentRoute,
}) { }) {
// Auto use the CupertinoPageRoute's title if middle not provided. // Auto use the CupertinoPageRoute's title if middle not provided.
if (automaticallyImplyTitle && if (automaticallyImplyTitle &&
currentRoute is CupertinoRouteTransitionMixin && currentRoute is CupertinoRouteTransitionMixin &&
currentRoute.title != null) { currentRoute.title != null) {
return Text(currentRoute.title); return Text(currentRoute.title!);
} }
return null; return null;
} }
final KeyedSubtree leading; final KeyedSubtree? leading;
static KeyedSubtree createLeading({ static KeyedSubtree? createLeading({
@required GlobalKey leadingKey, required GlobalKey leadingKey,
@required Widget userLeading, required Widget? userLeading,
@required ModalRoute<dynamic> route, required ModalRoute<dynamic>? route,
@required bool automaticallyImplyLeading, required bool automaticallyImplyLeading,
@required EdgeInsetsDirectional padding, required EdgeInsetsDirectional? padding,
}) { }) {
Widget leadingContent; Widget? leadingContent;
if (userLeading != null) { if (userLeading != null) {
leadingContent = userLeading; leadingContent = userLeading;
...@@ -1092,7 +1090,7 @@ class _NavigationBarStaticComponents { ...@@ -1092,7 +1090,7 @@ class _NavigationBarStaticComponents {
leadingContent = CupertinoButton( leadingContent = CupertinoButton(
child: const Text('Close'), child: const Text('Close'),
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
onPressed: () { route.navigator.maybePop(); }, onPressed: () { route.navigator!.maybePop(); },
); );
} }
...@@ -1116,12 +1114,12 @@ class _NavigationBarStaticComponents { ...@@ -1116,12 +1114,12 @@ class _NavigationBarStaticComponents {
); );
} }
final KeyedSubtree backChevron; final KeyedSubtree? backChevron;
static KeyedSubtree createBackChevron({ static KeyedSubtree? createBackChevron({
@required GlobalKey backChevronKey, required GlobalKey backChevronKey,
@required Widget userLeading, required Widget? userLeading,
@required ModalRoute<dynamic> route, required ModalRoute<dynamic>? route,
@required bool automaticallyImplyLeading, required bool automaticallyImplyLeading,
}) { }) {
if ( if (
userLeading != null || userLeading != null ||
...@@ -1138,13 +1136,13 @@ class _NavigationBarStaticComponents { ...@@ -1138,13 +1136,13 @@ class _NavigationBarStaticComponents {
/// This widget is not decorated with a font since the font style could /// This widget is not decorated with a font since the font style could
/// animate during transitions. /// animate during transitions.
final KeyedSubtree backLabel; final KeyedSubtree? backLabel;
static KeyedSubtree createBackLabel({ static KeyedSubtree? createBackLabel({
@required GlobalKey backLabelKey, required GlobalKey backLabelKey,
@required Widget userLeading, required Widget? userLeading,
@required ModalRoute<dynamic> route, required ModalRoute<dynamic>? route,
@required bool automaticallyImplyLeading, required bool automaticallyImplyLeading,
@required String previousPageTitle, required String? previousPageTitle,
}) { }) {
if ( if (
userLeading != null || userLeading != null ||
...@@ -1167,16 +1165,16 @@ class _NavigationBarStaticComponents { ...@@ -1167,16 +1165,16 @@ class _NavigationBarStaticComponents {
/// This widget is not decorated with a font since the font style could /// This widget is not decorated with a font since the font style could
/// animate during transitions. /// animate during transitions.
final KeyedSubtree middle; final KeyedSubtree? middle;
static KeyedSubtree createMiddle({ static KeyedSubtree? createMiddle({
@required GlobalKey middleKey, required GlobalKey middleKey,
@required Widget userMiddle, required Widget? userMiddle,
@required Widget userLargeTitle, required Widget? userLargeTitle,
@required bool large, required bool large,
@required bool automaticallyImplyTitle, required bool automaticallyImplyTitle,
@required ModalRoute<dynamic> route, required ModalRoute<dynamic>? route,
}) { }) {
Widget middleContent = userMiddle; Widget? middleContent = userMiddle;
if (large) { if (large) {
middleContent ??= userLargeTitle; middleContent ??= userLargeTitle;
...@@ -1197,11 +1195,11 @@ class _NavigationBarStaticComponents { ...@@ -1197,11 +1195,11 @@ class _NavigationBarStaticComponents {
); );
} }
final KeyedSubtree trailing; final KeyedSubtree? trailing;
static KeyedSubtree createTrailing({ static KeyedSubtree? createTrailing({
@required GlobalKey trailingKey, required GlobalKey trailingKey,
@required Widget userTrailing, required Widget? userTrailing,
@required EdgeInsetsDirectional padding, required EdgeInsetsDirectional? padding,
}) { }) {
if (userTrailing == null) { if (userTrailing == null) {
return null; return null;
...@@ -1225,19 +1223,19 @@ class _NavigationBarStaticComponents { ...@@ -1225,19 +1223,19 @@ class _NavigationBarStaticComponents {
/// This widget is not decorated with a font since the font style could /// This widget is not decorated with a font since the font style could
/// animate during transitions. /// animate during transitions.
final KeyedSubtree largeTitle; final KeyedSubtree? largeTitle;
static KeyedSubtree createLargeTitle({ static KeyedSubtree? createLargeTitle({
@required GlobalKey largeTitleKey, required GlobalKey largeTitleKey,
@required Widget userLargeTitle, required Widget? userLargeTitle,
@required bool large, required bool large,
@required bool automaticImplyTitle, required bool automaticImplyTitle,
@required ModalRoute<dynamic> route, required ModalRoute<dynamic>? route,
}) { }) {
if (!large) { if (!large) {
return null; return null;
} }
final Widget largeTitleContent = userLargeTitle ?? _derivedTitle( final Widget? largeTitleContent = userLargeTitle ?? _derivedTitle(
automaticallyImplyTitle: automaticImplyTitle, automaticallyImplyTitle: automaticImplyTitle,
currentRoute: route, currentRoute: route,
); );
...@@ -1249,7 +1247,7 @@ class _NavigationBarStaticComponents { ...@@ -1249,7 +1247,7 @@ class _NavigationBarStaticComponents {
return KeyedSubtree( return KeyedSubtree(
key: largeTitleKey, key: largeTitleKey,
child: largeTitleContent, child: largeTitleContent!,
); );
} }
} }
...@@ -1273,7 +1271,7 @@ class CupertinoNavigationBarBackButton extends StatelessWidget { ...@@ -1273,7 +1271,7 @@ class CupertinoNavigationBarBackButton extends StatelessWidget {
/// ///
/// The [color] parameter must not be null. /// The [color] parameter must not be null.
const CupertinoNavigationBarBackButton({ const CupertinoNavigationBarBackButton({
Key key, Key? key,
this.color, this.color,
this.previousPageTitle, this.previousPageTitle,
this.onPressed, this.onPressed,
...@@ -1295,12 +1293,12 @@ class CupertinoNavigationBarBackButton extends StatelessWidget { ...@@ -1295,12 +1293,12 @@ class CupertinoNavigationBarBackButton extends StatelessWidget {
/// Can be used to override the color of the back button chevron and label. /// Can be used to override the color of the back button chevron and label.
/// ///
/// Defaults to [CupertinoTheme]'s `primaryColor` if null. /// Defaults to [CupertinoTheme]'s `primaryColor` if null.
final Color color; final Color? color;
/// An override for showing the previous route's title. If null, it will be /// An override for showing the previous route's title. If null, it will be
/// automatically derived from [CupertinoPageRoute.title] if the current and /// automatically derived from [CupertinoPageRoute.title] if the current and
/// previous routes are both [CupertinoPageRoute]s. /// previous routes are both [CupertinoPageRoute]s.
final String previousPageTitle; final String? previousPageTitle;
/// An override callback to perform instead of the default behavior which is /// An override callback to perform instead of the default behavior which is
/// to pop the [Navigator]. /// to pop the [Navigator].
...@@ -1310,15 +1308,15 @@ class CupertinoNavigationBarBackButton extends StatelessWidget { ...@@ -1310,15 +1308,15 @@ class CupertinoNavigationBarBackButton extends StatelessWidget {
/// situations. /// situations.
/// ///
/// Defaults to null. /// Defaults to null.
final VoidCallback onPressed; final VoidCallback? onPressed;
final Widget _backChevron; final Widget? _backChevron;
final Widget _backLabel; final Widget? _backLabel;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final ModalRoute<dynamic> currentRoute = ModalRoute.of(context); final ModalRoute<dynamic>? currentRoute = ModalRoute.of(context);
if (onPressed == null) { if (onPressed == null) {
assert( assert(
currentRoute?.canPop == true, currentRoute?.canPop == true,
...@@ -1362,7 +1360,7 @@ class CupertinoNavigationBarBackButton extends StatelessWidget { ...@@ -1362,7 +1360,7 @@ class CupertinoNavigationBarBackButton extends StatelessWidget {
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
onPressed: () { onPressed: () {
if (onPressed != null) { if (onPressed != null) {
onPressed(); onPressed!();
} else { } else {
Navigator.maybePop(context); Navigator.maybePop(context);
} }
...@@ -1373,12 +1371,12 @@ class CupertinoNavigationBarBackButton extends StatelessWidget { ...@@ -1373,12 +1371,12 @@ class CupertinoNavigationBarBackButton extends StatelessWidget {
class _BackChevron extends StatelessWidget { class _BackChevron extends StatelessWidget {
const _BackChevron({ Key key }) : super(key: key); const _BackChevron({ Key? key }) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final TextDirection textDirection = Directionality.of(context); final TextDirection textDirection = Directionality.of(context)!;
final TextStyle textStyle = DefaultTextStyle.of(context).style; final TextStyle textStyle = DefaultTextStyle.of(context).style!;
// Replicate the Icon logic here to get a tightly sized icon and add // Replicate the Icon logic here to get a tightly sized icon and add
// custom non-square padding. // custom non-square padding.
...@@ -1415,17 +1413,17 @@ class _BackChevron extends StatelessWidget { ...@@ -1415,17 +1413,17 @@ class _BackChevron extends StatelessWidget {
/// is true. /// is true.
class _BackLabel extends StatelessWidget { class _BackLabel extends StatelessWidget {
const _BackLabel({ const _BackLabel({
Key key, Key? key,
@required this.specifiedPreviousTitle, required this.specifiedPreviousTitle,
@required this.route, required this.route,
}) : super(key: key); }) : super(key: key);
final String specifiedPreviousTitle; final String? specifiedPreviousTitle;
final ModalRoute<dynamic> route; final ModalRoute<dynamic>? route;
// `child` is never passed in into ValueListenableBuilder so it's always // `child` is never passed in into ValueListenableBuilder so it's always
// null here and unused. // null here and unused.
Widget _buildPreviousTitleWidget(BuildContext context, String previousTitle, Widget child) { Widget _buildPreviousTitleWidget(BuildContext context, String? previousTitle, Widget? child) {
if (previousTitle == null) { if (previousTitle == null) {
return const SizedBox(height: 0.0, width: 0.0); return const SizedBox(height: 0.0, width: 0.0);
} }
...@@ -1451,12 +1449,12 @@ class _BackLabel extends StatelessWidget { ...@@ -1451,12 +1449,12 @@ class _BackLabel extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
if (specifiedPreviousTitle != null) { if (specifiedPreviousTitle != null) {
return _buildPreviousTitleWidget(context, specifiedPreviousTitle, null); return _buildPreviousTitleWidget(context, specifiedPreviousTitle, null);
} else if (route is CupertinoRouteTransitionMixin<dynamic> && !route.isFirst) { } else if (route is CupertinoRouteTransitionMixin<dynamic> && !route!.isFirst) {
final CupertinoRouteTransitionMixin<dynamic> cupertinoRoute = route as CupertinoRouteTransitionMixin<dynamic>; final CupertinoRouteTransitionMixin<dynamic> cupertinoRoute = route as CupertinoRouteTransitionMixin<dynamic>;
// There is no timing issue because the previousTitle Listenable changes // There is no timing issue because the previousTitle Listenable changes
// happen during route modifications before the ValueListenableBuilder // happen during route modifications before the ValueListenableBuilder
// is built. // is built.
return ValueListenableBuilder<String>( return ValueListenableBuilder<String?>(
valueListenable: cupertinoRoute.previousTitle, valueListenable: cupertinoRoute.previousTitle,
builder: _buildPreviousTitleWidget, builder: _buildPreviousTitleWidget,
); );
...@@ -1476,32 +1474,32 @@ class _BackLabel extends StatelessWidget { ...@@ -1476,32 +1474,32 @@ class _BackLabel extends StatelessWidget {
/// navigation bar in each route. /// navigation bar in each route.
class _TransitionableNavigationBar extends StatelessWidget { class _TransitionableNavigationBar extends StatelessWidget {
_TransitionableNavigationBar({ _TransitionableNavigationBar({
@required this.componentsKeys, required this.componentsKeys,
@required this.backgroundColor, required this.backgroundColor,
@required this.backButtonTextStyle, required this.backButtonTextStyle,
@required this.titleTextStyle, required this.titleTextStyle,
@required this.largeTitleTextStyle, required this.largeTitleTextStyle,
@required this.border, required this.border,
@required this.hasUserMiddle, required this.hasUserMiddle,
@required this.largeExpanded, required this.largeExpanded,
@required this.child, required this.child,
}) : assert(componentsKeys != null), }) : assert(componentsKeys != null),
assert(largeExpanded != null), assert(largeExpanded != null),
assert(!largeExpanded || largeTitleTextStyle != null), assert(!largeExpanded || largeTitleTextStyle != null),
super(key: componentsKeys.navBarBoxKey); super(key: componentsKeys.navBarBoxKey);
final _NavigationBarStaticComponentsKeys componentsKeys; final _NavigationBarStaticComponentsKeys componentsKeys;
final Color backgroundColor; final Color? backgroundColor;
final TextStyle backButtonTextStyle; final TextStyle backButtonTextStyle;
final TextStyle titleTextStyle; final TextStyle titleTextStyle;
final TextStyle largeTitleTextStyle; final TextStyle? largeTitleTextStyle;
final Border border; final Border? border;
final bool hasUserMiddle; final bool hasUserMiddle;
final bool largeExpanded; final bool largeExpanded;
final Widget child; final Widget child;
RenderBox get renderBox { RenderBox get renderBox {
final RenderBox box = componentsKeys.navBarBoxKey.currentContext.findRenderObject() as RenderBox; final RenderBox box = componentsKeys.navBarBoxKey.currentContext!.findRenderObject() as RenderBox;
assert( assert(
box.attached, box.attached,
'_TransitionableNavigationBar.renderBox should be called when building ' '_TransitionableNavigationBar.renderBox should be called when building '
...@@ -1514,7 +1512,7 @@ class _TransitionableNavigationBar extends StatelessWidget { ...@@ -1514,7 +1512,7 @@ class _TransitionableNavigationBar extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
assert(() { assert(() {
bool inHero; bool inHero = false;
context.visitAncestorElements((Element ancestor) { context.visitAncestorElements((Element ancestor) {
if (ancestor is ComponentElement) { if (ancestor is ComponentElement) {
assert( assert(
...@@ -1528,11 +1526,10 @@ class _TransitionableNavigationBar extends StatelessWidget { ...@@ -1528,11 +1526,10 @@ class _TransitionableNavigationBar extends StatelessWidget {
inHero = true; inHero = true;
} }
} }
inHero ??= false;
return true; return true;
}); });
assert( assert(
inHero == true, inHero,
'_TransitionableNavigationBar should only be added as the immediate ' '_TransitionableNavigationBar should only be added as the immediate '
'child of Hero widgets.', 'child of Hero widgets.',
); );
...@@ -1559,9 +1556,9 @@ class _TransitionableNavigationBar extends StatelessWidget { ...@@ -1559,9 +1556,9 @@ class _TransitionableNavigationBar extends StatelessWidget {
/// results. /// results.
class _NavigationBarTransition extends StatelessWidget { class _NavigationBarTransition extends StatelessWidget {
_NavigationBarTransition({ _NavigationBarTransition({
@required this.animation, required this.animation,
@required this.topNavBar, required this.topNavBar,
@required this.bottomNavBar, required this.bottomNavBar,
}) : heightTween = Tween<double>( }) : heightTween = Tween<double>(
begin: bottomNavBar.renderBox.size.height, begin: bottomNavBar.renderBox.size.height,
end: topNavBar.renderBox.size.height, end: topNavBar.renderBox.size.height,
...@@ -1589,7 +1586,7 @@ class _NavigationBarTransition extends StatelessWidget { ...@@ -1589,7 +1586,7 @@ class _NavigationBarTransition extends StatelessWidget {
animation: animation, animation: animation,
bottomNavBar: bottomNavBar, bottomNavBar: bottomNavBar,
topNavBar: topNavBar, topNavBar: topNavBar,
directionality: Directionality.of(context), directionality: Directionality.of(context)!,
); );
final List<Widget> children = <Widget>[ final List<Widget> children = <Widget>[
...@@ -1597,11 +1594,11 @@ class _NavigationBarTransition extends StatelessWidget { ...@@ -1597,11 +1594,11 @@ class _NavigationBarTransition extends StatelessWidget {
// moving components without any components inside it itself. // moving components without any components inside it itself.
AnimatedBuilder( AnimatedBuilder(
animation: animation, animation: animation,
builder: (BuildContext context, Widget child) { builder: (BuildContext context, Widget? child) {
return _wrapWithBackground( return _wrapWithBackground(
// Don't update the system status bar color mid-flight. // Don't update the system status bar color mid-flight.
updateSystemUiOverlay: false, updateSystemUiOverlay: false,
backgroundColor: backgroundTween.evaluate(animation), backgroundColor: backgroundTween.evaluate(animation)!,
border: borderTween.evaluate(animation), border: borderTween.evaluate(animation),
child: SizedBox( child: SizedBox(
height: heightTween.evaluate(animation), height: heightTween.evaluate(animation),
...@@ -1611,29 +1608,28 @@ class _NavigationBarTransition extends StatelessWidget { ...@@ -1611,29 +1608,28 @@ class _NavigationBarTransition extends StatelessWidget {
}, },
), ),
// Draw all the components on top of the empty bar box. // Draw all the components on top of the empty bar box.
componentsTransition.bottomBackChevron, if (componentsTransition.bottomBackChevron != null) componentsTransition.bottomBackChevron!,
componentsTransition.bottomBackLabel, if (componentsTransition.bottomBackLabel != null) componentsTransition.bottomBackLabel!,
componentsTransition.bottomLeading, if (componentsTransition.bottomLeading != null) componentsTransition.bottomLeading!,
componentsTransition.bottomMiddle, if (componentsTransition.bottomMiddle != null) componentsTransition.bottomMiddle!,
componentsTransition.bottomLargeTitle, if (componentsTransition.bottomLargeTitle != null) componentsTransition.bottomLargeTitle!,
componentsTransition.bottomTrailing, if (componentsTransition.bottomTrailing != null) componentsTransition.bottomTrailing!,
// Draw top components on top of the bottom components. // Draw top components on top of the bottom components.
componentsTransition.topLeading, if (componentsTransition.topLeading != null) componentsTransition.topLeading!,
componentsTransition.topBackChevron, if (componentsTransition.topBackChevron != null) componentsTransition.topBackChevron!,
componentsTransition.topBackLabel, if (componentsTransition.topBackLabel != null) componentsTransition.topBackLabel!,
componentsTransition.topMiddle, if (componentsTransition.topMiddle != null) componentsTransition.topMiddle!,
componentsTransition.topLargeTitle, if (componentsTransition.topLargeTitle != null) componentsTransition.topLargeTitle!,
componentsTransition.topTrailing, if (componentsTransition.topTrailing != null) componentsTransition.topTrailing!,
]; ];
children.removeWhere((Widget child) => child == null);
// The actual outer box is big enough to contain both the bottom and top // The actual outer box is big enough to contain both the bottom and top
// navigation bars. It's not a direct Rect lerp because some components // navigation bars. It's not a direct Rect lerp because some components
// can actually be outside the linearly lerp'ed Rect in the middle of // can actually be outside the linearly lerp'ed Rect in the middle of
// the animation, such as the topLargeTitle. // the animation, such as the topLargeTitle.
return SizedBox( return SizedBox(
height: math.max(heightTween.begin, heightTween.end) + MediaQuery.of(context).padding.top, height: math.max(heightTween.begin!, heightTween.end!) + MediaQuery.of(context)!.padding.top,
width: double.infinity, width: double.infinity,
child: Stack( child: Stack(
children: children, children: children,
...@@ -1666,10 +1662,10 @@ class _NavigationBarTransition extends StatelessWidget { ...@@ -1666,10 +1662,10 @@ class _NavigationBarTransition extends StatelessWidget {
@immutable @immutable
class _NavigationBarComponentsTransition { class _NavigationBarComponentsTransition {
_NavigationBarComponentsTransition({ _NavigationBarComponentsTransition({
@required this.animation, required this.animation,
@required _TransitionableNavigationBar bottomNavBar, required _TransitionableNavigationBar bottomNavBar,
@required _TransitionableNavigationBar topNavBar, required _TransitionableNavigationBar topNavBar,
@required TextDirection directionality, required TextDirection directionality,
}) : bottomComponents = bottomNavBar.componentsKeys, }) : bottomComponents = bottomNavBar.componentsKeys,
topComponents = topNavBar.componentsKeys, topComponents = topNavBar.componentsKeys,
bottomNavBarBox = bottomNavBar.renderBox, bottomNavBarBox = bottomNavBar.renderBox,
...@@ -1712,8 +1708,8 @@ class _NavigationBarComponentsTransition { ...@@ -1712,8 +1708,8 @@ class _NavigationBarComponentsTransition {
final TextStyle topBackButtonTextStyle; final TextStyle topBackButtonTextStyle;
final TextStyle bottomTitleTextStyle; final TextStyle bottomTitleTextStyle;
final TextStyle topTitleTextStyle; final TextStyle topTitleTextStyle;
final TextStyle bottomLargeTitleTextStyle; final TextStyle? bottomLargeTitleTextStyle;
final TextStyle topLargeTitleTextStyle; final TextStyle? topLargeTitleTextStyle;
final bool bottomHasUserMiddle; final bool bottomHasUserMiddle;
final bool topHasUserMiddle; final bool topHasUserMiddle;
...@@ -1731,9 +1727,9 @@ class _NavigationBarComponentsTransition { ...@@ -1731,9 +1727,9 @@ class _NavigationBarComponentsTransition {
// translate it into a RelativeBox in the transition navigation bar box. // translate it into a RelativeBox in the transition navigation bar box.
RelativeRect positionInTransitionBox( RelativeRect positionInTransitionBox(
GlobalKey key, { GlobalKey key, {
@required RenderBox from, required RenderBox from,
}) { }) {
final RenderBox componentBox = key.currentContext.findRenderObject() as RenderBox; final RenderBox componentBox = key.currentContext!.findRenderObject() as RenderBox;
assert(componentBox.attached); assert(componentBox.attached);
return RelativeRect.fromRect( return RelativeRect.fromRect(
...@@ -1753,15 +1749,15 @@ class _NavigationBarComponentsTransition { ...@@ -1753,15 +1749,15 @@ class _NavigationBarComponentsTransition {
// BoxConstraints of the 'from' widget so that animating font sizes etc don't // BoxConstraints of the 'from' widget so that animating font sizes etc don't
// produce rounding error artifacts with a linearly resizing rect. // produce rounding error artifacts with a linearly resizing rect.
RelativeRectTween slideFromLeadingEdge({ RelativeRectTween slideFromLeadingEdge({
@required GlobalKey fromKey, required GlobalKey fromKey,
@required RenderBox fromNavBarBox, required RenderBox fromNavBarBox,
@required GlobalKey toKey, required GlobalKey toKey,
@required RenderBox toNavBarBox, required RenderBox toNavBarBox,
}) { }) {
final RelativeRect fromRect = positionInTransitionBox(fromKey, from: fromNavBarBox); final RelativeRect fromRect = positionInTransitionBox(fromKey, from: fromNavBarBox);
final RenderBox fromBox = fromKey.currentContext.findRenderObject() as RenderBox; final RenderBox fromBox = fromKey.currentContext!.findRenderObject() as RenderBox;
final RenderBox toBox = toKey.currentContext.findRenderObject() as RenderBox; final RenderBox toBox = toKey.currentContext!.findRenderObject() as RenderBox;
// We move a box with the size of the 'from' render object such that its // We move a box with the size of the 'from' render object such that its
// upper left corner is at the upper left corner of the 'to' render object. // upper left corner is at the upper left corner of the 'to' render object.
...@@ -1799,8 +1795,8 @@ class _NavigationBarComponentsTransition { ...@@ -1799,8 +1795,8 @@ class _NavigationBarComponentsTransition {
)); ));
} }
Widget get bottomLeading { Widget? get bottomLeading {
final KeyedSubtree bottomLeading = bottomComponents.leadingKey.currentWidget as KeyedSubtree; final KeyedSubtree? bottomLeading = bottomComponents.leadingKey.currentWidget as KeyedSubtree?;
if (bottomLeading == null) { if (bottomLeading == null) {
return null; return null;
...@@ -1815,8 +1811,8 @@ class _NavigationBarComponentsTransition { ...@@ -1815,8 +1811,8 @@ class _NavigationBarComponentsTransition {
); );
} }
Widget get bottomBackChevron { Widget? get bottomBackChevron {
final KeyedSubtree bottomBackChevron = bottomComponents.backChevronKey.currentWidget as KeyedSubtree; final KeyedSubtree? bottomBackChevron = bottomComponents.backChevronKey.currentWidget as KeyedSubtree?;
if (bottomBackChevron == null) { if (bottomBackChevron == null) {
return null; return null;
...@@ -1834,8 +1830,8 @@ class _NavigationBarComponentsTransition { ...@@ -1834,8 +1830,8 @@ class _NavigationBarComponentsTransition {
); );
} }
Widget get bottomBackLabel { Widget? get bottomBackLabel {
final KeyedSubtree bottomBackLabel = bottomComponents.backLabelKey.currentWidget as KeyedSubtree; final KeyedSubtree? bottomBackLabel = bottomComponents.backLabelKey.currentWidget as KeyedSubtree?;
if (bottomBackLabel == null) { if (bottomBackLabel == null) {
return null; return null;
...@@ -1866,10 +1862,10 @@ class _NavigationBarComponentsTransition { ...@@ -1866,10 +1862,10 @@ class _NavigationBarComponentsTransition {
); );
} }
Widget get bottomMiddle { Widget? get bottomMiddle {
final KeyedSubtree bottomMiddle = bottomComponents.middleKey.currentWidget as KeyedSubtree; final KeyedSubtree? bottomMiddle = bottomComponents.middleKey.currentWidget as KeyedSubtree?;
final KeyedSubtree topBackLabel = topComponents.backLabelKey.currentWidget as KeyedSubtree; final KeyedSubtree? topBackLabel = topComponents.backLabelKey.currentWidget as KeyedSubtree?;
final KeyedSubtree topLeading = topComponents.leadingKey.currentWidget as KeyedSubtree; final KeyedSubtree? topLeading = topComponents.leadingKey.currentWidget as KeyedSubtree?;
// The middle component is non-null when the nav bar is a large title // The middle component is non-null when the nav bar is a large title
// nav bar but would be invisible when expanded, therefore don't show it here. // nav bar but would be invisible when expanded, therefore don't show it here.
...@@ -1925,10 +1921,10 @@ class _NavigationBarComponentsTransition { ...@@ -1925,10 +1921,10 @@ class _NavigationBarComponentsTransition {
return null; return null;
} }
Widget get bottomLargeTitle { Widget? get bottomLargeTitle {
final KeyedSubtree bottomLargeTitle = bottomComponents.largeTitleKey.currentWidget as KeyedSubtree; final KeyedSubtree? bottomLargeTitle = bottomComponents.largeTitleKey.currentWidget as KeyedSubtree?;
final KeyedSubtree topBackLabel = topComponents.backLabelKey.currentWidget as KeyedSubtree; final KeyedSubtree? topBackLabel = topComponents.backLabelKey.currentWidget as KeyedSubtree?;
final KeyedSubtree topLeading = topComponents.leadingKey.currentWidget as KeyedSubtree; final KeyedSubtree? topLeading = topComponents.leadingKey.currentWidget as KeyedSubtree?;
if (bottomLargeTitle == null || !bottomLargeExpanded) { if (bottomLargeTitle == null || !bottomLargeExpanded) {
return null; return null;
...@@ -1996,8 +1992,8 @@ class _NavigationBarComponentsTransition { ...@@ -1996,8 +1992,8 @@ class _NavigationBarComponentsTransition {
return null; return null;
} }
Widget get bottomTrailing { Widget? get bottomTrailing {
final KeyedSubtree bottomTrailing = bottomComponents.trailingKey.currentWidget as KeyedSubtree; final KeyedSubtree? bottomTrailing = bottomComponents.trailingKey.currentWidget as KeyedSubtree?;
if (bottomTrailing == null) { if (bottomTrailing == null) {
return null; return null;
...@@ -2012,8 +2008,8 @@ class _NavigationBarComponentsTransition { ...@@ -2012,8 +2008,8 @@ class _NavigationBarComponentsTransition {
); );
} }
Widget get topLeading { Widget? get topLeading {
final KeyedSubtree topLeading = topComponents.leadingKey.currentWidget as KeyedSubtree; final KeyedSubtree? topLeading = topComponents.leadingKey.currentWidget as KeyedSubtree?;
if (topLeading == null) { if (topLeading == null) {
return null; return null;
...@@ -2028,9 +2024,9 @@ class _NavigationBarComponentsTransition { ...@@ -2028,9 +2024,9 @@ class _NavigationBarComponentsTransition {
); );
} }
Widget get topBackChevron { Widget? get topBackChevron {
final KeyedSubtree topBackChevron = topComponents.backChevronKey.currentWidget as KeyedSubtree; final KeyedSubtree? topBackChevron = topComponents.backChevronKey.currentWidget as KeyedSubtree?;
final KeyedSubtree bottomBackChevron = bottomComponents.backChevronKey.currentWidget as KeyedSubtree; final KeyedSubtree? bottomBackChevron = bottomComponents.backChevronKey.currentWidget as KeyedSubtree?;
if (topBackChevron == null) { if (topBackChevron == null) {
return null; return null;
...@@ -2042,7 +2038,7 @@ class _NavigationBarComponentsTransition { ...@@ -2042,7 +2038,7 @@ class _NavigationBarComponentsTransition {
// If it's the first page with a back chevron, shift in slightly from the // If it's the first page with a back chevron, shift in slightly from the
// right. // right.
if (bottomBackChevron == null) { if (bottomBackChevron == null) {
final RenderBox topBackChevronBox = topComponents.backChevronKey.currentContext.findRenderObject() as RenderBox; final RenderBox topBackChevronBox = topComponents.backChevronKey.currentContext!.findRenderObject() as RenderBox;
from = to.shift( from = to.shift(
Offset( Offset(
forwardDirection * topBackChevronBox.size.width * 2.0, forwardDirection * topBackChevronBox.size.width * 2.0,
...@@ -2068,19 +2064,19 @@ class _NavigationBarComponentsTransition { ...@@ -2068,19 +2064,19 @@ class _NavigationBarComponentsTransition {
); );
} }
Widget get topBackLabel { Widget? get topBackLabel {
final KeyedSubtree bottomMiddle = bottomComponents.middleKey.currentWidget as KeyedSubtree; final KeyedSubtree? bottomMiddle = bottomComponents.middleKey.currentWidget as KeyedSubtree?;
final KeyedSubtree bottomLargeTitle = bottomComponents.largeTitleKey.currentWidget as KeyedSubtree; final KeyedSubtree? bottomLargeTitle = bottomComponents.largeTitleKey.currentWidget as KeyedSubtree?;
final KeyedSubtree topBackLabel = topComponents.backLabelKey.currentWidget as KeyedSubtree; final KeyedSubtree? topBackLabel = topComponents.backLabelKey.currentWidget as KeyedSubtree?;
if (topBackLabel == null) { if (topBackLabel == null) {
return null; return null;
} }
final RenderAnimatedOpacity topBackLabelOpacity = final RenderAnimatedOpacity? topBackLabelOpacity =
topComponents.backLabelKey.currentContext?.findAncestorRenderObjectOfType<RenderAnimatedOpacity>(); topComponents.backLabelKey.currentContext?.findAncestorRenderObjectOfType<RenderAnimatedOpacity>();
Animation<double> midClickOpacity; Animation<double>? midClickOpacity;
if (topBackLabelOpacity != null && topBackLabelOpacity.opacity.value < 1.0) { if (topBackLabelOpacity != null && topBackLabelOpacity.opacity.value < 1.0) {
midClickOpacity = animation.drive(Tween<double>( midClickOpacity = animation.drive(Tween<double>(
begin: 0.0, begin: 0.0,
...@@ -2144,8 +2140,8 @@ class _NavigationBarComponentsTransition { ...@@ -2144,8 +2140,8 @@ class _NavigationBarComponentsTransition {
return null; return null;
} }
Widget get topMiddle { Widget? get topMiddle {
final KeyedSubtree topMiddle = topComponents.middleKey.currentWidget as KeyedSubtree; final KeyedSubtree? topMiddle = topComponents.middleKey.currentWidget as KeyedSubtree?;
if (topMiddle == null) { if (topMiddle == null) {
return null; return null;
...@@ -2182,8 +2178,8 @@ class _NavigationBarComponentsTransition { ...@@ -2182,8 +2178,8 @@ class _NavigationBarComponentsTransition {
); );
} }
Widget get topTrailing { Widget? get topTrailing {
final KeyedSubtree topTrailing = topComponents.trailingKey.currentWidget as KeyedSubtree; final KeyedSubtree? topTrailing = topComponents.trailingKey.currentWidget as KeyedSubtree?;
if (topTrailing == null) { if (topTrailing == null) {
return null; return null;
...@@ -2198,8 +2194,8 @@ class _NavigationBarComponentsTransition { ...@@ -2198,8 +2194,8 @@ class _NavigationBarComponentsTransition {
); );
} }
Widget get topLargeTitle { Widget? get topLargeTitle {
final KeyedSubtree topLargeTitle = topComponents.largeTitleKey.currentWidget as KeyedSubtree; final KeyedSubtree? topLargeTitle = topComponents.largeTitleKey.currentWidget as KeyedSubtree?;
if (topLargeTitle == null || !topLargeExpanded) { if (topLargeTitle == null || !topLargeExpanded) {
return null; return null;
...@@ -2235,9 +2231,9 @@ class _NavigationBarComponentsTransition { ...@@ -2235,9 +2231,9 @@ class _NavigationBarComponentsTransition {
/// Navigation bars' hero rect tween that will move between the static bars /// Navigation bars' hero rect tween that will move between the static bars
/// but keep a constant size that's the bigger of both navigation bars. /// but keep a constant size that's the bigger of both navigation bars.
CreateRectTween _linearTranslateWithLargestRectSizeTween = (Rect begin, Rect end) { CreateRectTween _linearTranslateWithLargestRectSizeTween = (Rect? begin, Rect? end) {
final Size largestSize = Size( final Size largestSize = Size(
math.max(begin.size.width, end.size.width), math.max(begin!.size.width, end!.size.width),
math.max(begin.size.height, end.size.height), math.max(begin.size.height, end.size.height),
); );
return RectTween( return RectTween(
...@@ -2300,11 +2296,11 @@ final HeroFlightShuttleBuilder _navBarHeroFlightShuttleBuilder = ( ...@@ -2300,11 +2296,11 @@ final HeroFlightShuttleBuilder _navBarHeroFlightShuttleBuilder = (
assert(toNavBar.componentsKeys != null); assert(toNavBar.componentsKeys != null);
assert( assert(
fromNavBar.componentsKeys.navBarBoxKey.currentContext.owner != null, fromNavBar.componentsKeys.navBarBoxKey.currentContext!.owner != null,
'The from nav bar to Hero must have been mounted in the previous frame', 'The from nav bar to Hero must have been mounted in the previous frame',
); );
assert( assert(
toNavBar.componentsKeys.navBarBoxKey.currentContext.owner != null, toNavBar.componentsKeys.navBarBoxKey.currentContext!.owner != null,
'The to nav bar to Hero must have been mounted in the previous frame', 'The to nav bar to Hero must have been mounted in the previous frame',
); );
...@@ -2315,7 +2311,6 @@ final HeroFlightShuttleBuilder _navBarHeroFlightShuttleBuilder = ( ...@@ -2315,7 +2311,6 @@ final HeroFlightShuttleBuilder _navBarHeroFlightShuttleBuilder = (
bottomNavBar: fromNavBar, bottomNavBar: fromNavBar,
topNavBar: toNavBar, topNavBar: toNavBar,
); );
break;
case HeroFlightDirection.pop: case HeroFlightDirection.pop:
return _NavigationBarTransition( return _NavigationBarTransition(
animation: animation, animation: animation,
...@@ -2323,5 +2318,4 @@ final HeroFlightShuttleBuilder _navBarHeroFlightShuttleBuilder = ( ...@@ -2323,5 +2318,4 @@ final HeroFlightShuttleBuilder _navBarHeroFlightShuttleBuilder = (
topNavBar: fromNavBar, topNavBar: fromNavBar,
); );
} }
return null;
}; };
...@@ -2,8 +2,6 @@ ...@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// @dart = 2.8
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'colors.dart'; import 'colors.dart';
...@@ -22,11 +20,11 @@ import 'theme.dart'; ...@@ -22,11 +20,11 @@ import 'theme.dart';
class CupertinoPageScaffold extends StatefulWidget { class CupertinoPageScaffold extends StatefulWidget {
/// Creates a layout for pages with a navigation bar at the top. /// Creates a layout for pages with a navigation bar at the top.
const CupertinoPageScaffold({ const CupertinoPageScaffold({
Key key, Key? key,
this.navigationBar, this.navigationBar,
this.backgroundColor, this.backgroundColor,
this.resizeToAvoidBottomInset = true, this.resizeToAvoidBottomInset = true,
@required this.child, required this.child,
}) : assert(child != null), }) : assert(child != null),
assert(resizeToAvoidBottomInset != null), assert(resizeToAvoidBottomInset != null),
super(key: key); super(key: key);
...@@ -48,7 +46,7 @@ class CupertinoPageScaffold extends StatefulWidget { ...@@ -48,7 +46,7 @@ class CupertinoPageScaffold extends StatefulWidget {
/// in many ways, such as querying [MediaQuery.textScaleFactorOf] against /// in many ways, such as querying [MediaQuery.textScaleFactorOf] against
/// [CupertinoApp]'s [BuildContext]. /// [CupertinoApp]'s [BuildContext].
// TODO(xster): document its page transition animation when ready // TODO(xster): document its page transition animation when ready
final ObstructingPreferredSizeWidget navigationBar; final ObstructingPreferredSizeWidget? navigationBar;
/// Widget to show in the main content area. /// Widget to show in the main content area.
/// ///
...@@ -61,7 +59,7 @@ class CupertinoPageScaffold extends StatefulWidget { ...@@ -61,7 +59,7 @@ class CupertinoPageScaffold extends StatefulWidget {
/// The color of the widget that underlies the entire scaffold. /// The color of the widget that underlies the entire scaffold.
/// ///
/// By default uses [CupertinoTheme]'s `scaffoldBackgroundColor` when null. /// By default uses [CupertinoTheme]'s `scaffoldBackgroundColor` when null.
final Color backgroundColor; final Color? backgroundColor;
/// Whether the [child] should size itself to avoid the window's bottom inset. /// Whether the [child] should size itself to avoid the window's bottom inset.
/// ///
...@@ -95,12 +93,12 @@ class _CupertinoPageScaffoldState extends State<CupertinoPageScaffold> { ...@@ -95,12 +93,12 @@ class _CupertinoPageScaffoldState extends State<CupertinoPageScaffold> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
Widget paddedContent = widget.child; Widget paddedContent = widget.child;
final MediaQueryData existingMediaQuery = MediaQuery.of(context); final MediaQueryData existingMediaQuery = MediaQuery.of(context)!;
if (widget.navigationBar != null) { if (widget.navigationBar != null) {
// TODO(xster): Use real size after partial layout instead of preferred size. // TODO(xster): Use real size after partial layout instead of preferred size.
// https://github.com/flutter/flutter/issues/12912 // https://github.com/flutter/flutter/issues/12912
final double topPadding = final double topPadding =
widget.navigationBar.preferredSize.height + existingMediaQuery.padding.top; widget.navigationBar!.preferredSize.height + existingMediaQuery.padding.top;
// Propagate bottom padding and include viewInsets if appropriate // Propagate bottom padding and include viewInsets if appropriate
final double bottomPadding = widget.resizeToAvoidBottomInset final double bottomPadding = widget.resizeToAvoidBottomInset
...@@ -113,7 +111,7 @@ class _CupertinoPageScaffoldState extends State<CupertinoPageScaffold> { ...@@ -113,7 +111,7 @@ class _CupertinoPageScaffoldState extends State<CupertinoPageScaffold> {
? existingMediaQuery.viewInsets.copyWith(bottom: 0.0) ? existingMediaQuery.viewInsets.copyWith(bottom: 0.0)
: existingMediaQuery.viewInsets; : existingMediaQuery.viewInsets;
final bool fullObstruction = widget.navigationBar.shouldFullyObstruct(context); final bool fullObstruction = widget.navigationBar!.shouldFullyObstruct(context);
// If navigation bar is opaquely obstructing, directly shift the main content // If navigation bar is opaquely obstructing, directly shift the main content
// down. If translucent, let main content draw behind navigation bar but hint the // down. If translucent, let main content draw behind navigation bar but hint the
...@@ -176,7 +174,7 @@ class _CupertinoPageScaffoldState extends State<CupertinoPageScaffold> { ...@@ -176,7 +174,7 @@ class _CupertinoPageScaffoldState extends State<CupertinoPageScaffold> {
right: 0.0, right: 0.0,
child: MediaQuery( child: MediaQuery(
data: existingMediaQuery.copyWith(textScaleFactor: 1), data: existingMediaQuery.copyWith(textScaleFactor: 1),
child: widget.navigationBar, child: widget.navigationBar!,
), ),
), ),
// Add a touch handler the size of the status bar on top of all contents // Add a touch handler the size of the status bar on top of all contents
......
...@@ -2,8 +2,6 @@ ...@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// @dart = 2.8
import 'dart:collection'; import 'dart:collection';
import 'dart:math' as math; import 'dart:math' as math;
...@@ -66,7 +64,7 @@ const Duration _kFadeDuration = Duration(milliseconds: 165); ...@@ -66,7 +64,7 @@ const Duration _kFadeDuration = Duration(milliseconds: 165);
/// * [CupertinoSegmentedControl], a segmented control widget in the style used /// * [CupertinoSegmentedControl], a segmented control widget in the style used
/// up until iOS 13. /// up until iOS 13.
/// * <https://developer.apple.com/design/human-interface-guidelines/ios/controls/segmented-controls/> /// * <https://developer.apple.com/design/human-interface-guidelines/ios/controls/segmented-controls/>
class CupertinoSegmentedControl<T> extends StatefulWidget { class CupertinoSegmentedControl<T extends Object> extends StatefulWidget {
/// Creates an iOS-style segmented control bar. /// Creates an iOS-style segmented control bar.
/// ///
/// The [children] and [onValueChanged] arguments must not be null. The /// The [children] and [onValueChanged] arguments must not be null. The
...@@ -83,9 +81,9 @@ class CupertinoSegmentedControl<T> extends StatefulWidget { ...@@ -83,9 +81,9 @@ class CupertinoSegmentedControl<T> extends StatefulWidget {
/// appear as selected. The [groupValue] must be either null or one of the keys /// appear as selected. The [groupValue] must be either null or one of the keys
/// in the [children] map. /// in the [children] map.
CupertinoSegmentedControl({ CupertinoSegmentedControl({
Key key, Key? key,
@required this.children, required this.children,
@required this.onValueChanged, required this.onValueChanged,
this.groupValue, this.groupValue,
this.unselectedColor, this.unselectedColor,
this.selectedColor, this.selectedColor,
...@@ -112,7 +110,7 @@ class CupertinoSegmentedControl<T> extends StatefulWidget { ...@@ -112,7 +110,7 @@ class CupertinoSegmentedControl<T> extends StatefulWidget {
/// ///
/// This must be one of the keys in the [Map] of [children]. /// This must be one of the keys in the [Map] of [children].
/// If this attribute is null, no widget will be initially selected. /// If this attribute is null, no widget will be initially selected.
final T groupValue; final T? groupValue;
/// The callback that is called when a new option is tapped. /// The callback that is called when a new option is tapped.
/// ///
...@@ -165,49 +163,49 @@ class CupertinoSegmentedControl<T> extends StatefulWidget { ...@@ -165,49 +163,49 @@ class CupertinoSegmentedControl<T> extends StatefulWidget {
/// text color of the selected widget. /// text color of the selected widget.
/// ///
/// Defaults to [CupertinoTheme]'s `primaryContrastingColor` if null. /// Defaults to [CupertinoTheme]'s `primaryContrastingColor` if null.
final Color unselectedColor; final Color? unselectedColor;
/// The color used to fill the background of the selected widget and as the text /// The color used to fill the background of the selected widget and as the text
/// color of unselected widgets. /// color of unselected widgets.
/// ///
/// Defaults to [CupertinoTheme]'s `primaryColor` if null. /// Defaults to [CupertinoTheme]'s `primaryColor` if null.
final Color selectedColor; final Color? selectedColor;
/// The color used as the border around each widget. /// The color used as the border around each widget.
/// ///
/// Defaults to [CupertinoTheme]'s `primaryColor` if null. /// Defaults to [CupertinoTheme]'s `primaryColor` if null.
final Color borderColor; final Color? borderColor;
/// The color used to fill the background of the widget the user is /// The color used to fill the background of the widget the user is
/// temporarily interacting with through a long press or drag. /// temporarily interacting with through a long press or drag.
/// ///
/// Defaults to the selectedColor at 20% opacity if null. /// Defaults to the selectedColor at 20% opacity if null.
final Color pressedColor; final Color? pressedColor;
/// The CupertinoSegmentedControl will be placed inside this padding. /// The CupertinoSegmentedControl will be placed inside this padding.
/// ///
/// Defaults to EdgeInsets.symmetric(horizontal: 16.0) /// Defaults to EdgeInsets.symmetric(horizontal: 16.0)
final EdgeInsetsGeometry padding; final EdgeInsetsGeometry? padding;
@override @override
_SegmentedControlState<T> createState() => _SegmentedControlState<T>(); _SegmentedControlState<T> createState() => _SegmentedControlState<T>();
} }
class _SegmentedControlState<T> extends State<CupertinoSegmentedControl<T>> class _SegmentedControlState<T extends Object> extends State<CupertinoSegmentedControl<T>>
with TickerProviderStateMixin<CupertinoSegmentedControl<T>> { with TickerProviderStateMixin<CupertinoSegmentedControl<T>> {
T _pressedKey; T? _pressedKey;
final List<AnimationController> _selectionControllers = <AnimationController>[]; final List<AnimationController> _selectionControllers = <AnimationController>[];
final List<ColorTween> _childTweens = <ColorTween>[]; final List<ColorTween> _childTweens = <ColorTween>[];
ColorTween _forwardBackgroundColorTween; late ColorTween _forwardBackgroundColorTween;
ColorTween _reverseBackgroundColorTween; late ColorTween _reverseBackgroundColorTween;
ColorTween _textColorTween; late ColorTween _textColorTween;
Color _selectedColor; Color? _selectedColor;
Color _unselectedColor; Color? _unselectedColor;
Color _borderColor; Color? _borderColor;
Color _pressedColor; Color? _pressedColor;
AnimationController createAnimationController() { AnimationController createAnimationController() {
return AnimationController( return AnimationController(
...@@ -343,7 +341,7 @@ class _SegmentedControlState<T> extends State<CupertinoSegmentedControl<T>> ...@@ -343,7 +341,7 @@ class _SegmentedControlState<T> extends State<CupertinoSegmentedControl<T>>
_pressedKey = null; _pressedKey = null;
} }
Color getTextColor(int index, T currentKey) { Color? getTextColor(int index, T currentKey) {
if (_selectionControllers[index].isAnimating) if (_selectionControllers[index].isAnimating)
return _textColorTween.evaluate(_selectionControllers[index]); return _textColorTween.evaluate(_selectionControllers[index]);
if (widget.groupValue == currentKey) if (widget.groupValue == currentKey)
...@@ -351,7 +349,7 @@ class _SegmentedControlState<T> extends State<CupertinoSegmentedControl<T>> ...@@ -351,7 +349,7 @@ class _SegmentedControlState<T> extends State<CupertinoSegmentedControl<T>>
return _selectedColor; return _selectedColor;
} }
Color getBackgroundColor(int index, T currentKey) { Color? getBackgroundColor(int index, T currentKey) {
if (_selectionControllers[index].isAnimating) if (_selectionControllers[index].isAnimating)
return _childTweens[index].evaluate(_selectionControllers[index]); return _childTweens[index].evaluate(_selectionControllers[index]);
if (widget.groupValue == currentKey) if (widget.groupValue == currentKey)
...@@ -366,13 +364,13 @@ class _SegmentedControlState<T> extends State<CupertinoSegmentedControl<T>> ...@@ -366,13 +364,13 @@ class _SegmentedControlState<T> extends State<CupertinoSegmentedControl<T>>
final List<Widget> _gestureChildren = <Widget>[]; final List<Widget> _gestureChildren = <Widget>[];
final List<Color> _backgroundColors = <Color>[]; final List<Color> _backgroundColors = <Color>[];
int index = 0; int index = 0;
int selectedIndex; int? selectedIndex;
int pressedIndex; int? pressedIndex;
for (final T currentKey in widget.children.keys) { for (final T currentKey in widget.children.keys) {
selectedIndex = (widget.groupValue == currentKey) ? index : selectedIndex; selectedIndex = (widget.groupValue == currentKey) ? index : selectedIndex;
pressedIndex = (_pressedKey == currentKey) ? index : pressedIndex; pressedIndex = (_pressedKey == currentKey) ? index : pressedIndex;
final TextStyle textStyle = DefaultTextStyle.of(context).style.copyWith( final TextStyle textStyle = DefaultTextStyle.of(context).style!.copyWith(
color: getTextColor(index, currentKey), color: getTextColor(index, currentKey),
); );
final IconThemeData iconTheme = IconThemeData( final IconThemeData iconTheme = IconThemeData(
...@@ -406,7 +404,7 @@ class _SegmentedControlState<T> extends State<CupertinoSegmentedControl<T>> ...@@ -406,7 +404,7 @@ class _SegmentedControlState<T> extends State<CupertinoSegmentedControl<T>>
), ),
); );
_backgroundColors.add(getBackgroundColor(index, currentKey)); _backgroundColors.add(getBackgroundColor(index, currentKey)!);
_gestureChildren.add(child); _gestureChildren.add(child);
index += 1; index += 1;
} }
...@@ -416,7 +414,7 @@ class _SegmentedControlState<T> extends State<CupertinoSegmentedControl<T>> ...@@ -416,7 +414,7 @@ class _SegmentedControlState<T> extends State<CupertinoSegmentedControl<T>>
selectedIndex: selectedIndex, selectedIndex: selectedIndex,
pressedIndex: pressedIndex, pressedIndex: pressedIndex,
backgroundColors: _backgroundColors, backgroundColors: _backgroundColors,
borderColor: _borderColor, borderColor: _borderColor!,
); );
return Padding( return Padding(
...@@ -431,26 +429,26 @@ class _SegmentedControlState<T> extends State<CupertinoSegmentedControl<T>> ...@@ -431,26 +429,26 @@ class _SegmentedControlState<T> extends State<CupertinoSegmentedControl<T>>
class _SegmentedControlRenderWidget<T> extends MultiChildRenderObjectWidget { class _SegmentedControlRenderWidget<T> extends MultiChildRenderObjectWidget {
_SegmentedControlRenderWidget({ _SegmentedControlRenderWidget({
Key key, Key? key,
List<Widget> children = const <Widget>[], List<Widget> children = const <Widget>[],
@required this.selectedIndex, required this.selectedIndex,
@required this.pressedIndex, required this.pressedIndex,
@required this.backgroundColors, required this.backgroundColors,
@required this.borderColor, required this.borderColor,
}) : super( }) : super(
key: key, key: key,
children: children, children: children,
); );
final int selectedIndex; final int? selectedIndex;
final int pressedIndex; final int? pressedIndex;
final List<Color> backgroundColors; final List<Color> backgroundColors;
final Color borderColor; final Color borderColor;
@override @override
RenderObject createRenderObject(BuildContext context) { RenderObject createRenderObject(BuildContext context) {
return _RenderSegmentedControl<T>( return _RenderSegmentedControl<T>(
textDirection: Directionality.of(context), textDirection: Directionality.of(context)!,
selectedIndex: selectedIndex, selectedIndex: selectedIndex,
pressedIndex: pressedIndex, pressedIndex: pressedIndex,
backgroundColors: backgroundColors, backgroundColors: backgroundColors,
...@@ -461,7 +459,7 @@ class _SegmentedControlRenderWidget<T> extends MultiChildRenderObjectWidget { ...@@ -461,7 +459,7 @@ class _SegmentedControlRenderWidget<T> extends MultiChildRenderObjectWidget {
@override @override
void updateRenderObject(BuildContext context, _RenderSegmentedControl<T> renderObject) { void updateRenderObject(BuildContext context, _RenderSegmentedControl<T> renderObject) {
renderObject renderObject
..textDirection = Directionality.of(context) ..textDirection = Directionality.of(context)!
..selectedIndex = selectedIndex ..selectedIndex = selectedIndex
..pressedIndex = pressedIndex ..pressedIndex = pressedIndex
..backgroundColors = backgroundColors ..backgroundColors = backgroundColors
...@@ -470,20 +468,20 @@ class _SegmentedControlRenderWidget<T> extends MultiChildRenderObjectWidget { ...@@ -470,20 +468,20 @@ class _SegmentedControlRenderWidget<T> extends MultiChildRenderObjectWidget {
} }
class _SegmentedControlContainerBoxParentData extends ContainerBoxParentData<RenderBox> { class _SegmentedControlContainerBoxParentData extends ContainerBoxParentData<RenderBox> {
RRect surroundingRect; RRect? surroundingRect;
} }
typedef _NextChild = RenderBox Function(RenderBox child); typedef _NextChild = RenderBox? Function(RenderBox child);
class _RenderSegmentedControl<T> extends RenderBox class _RenderSegmentedControl<T> extends RenderBox
with ContainerRenderObjectMixin<RenderBox, ContainerBoxParentData<RenderBox>>, with ContainerRenderObjectMixin<RenderBox, ContainerBoxParentData<RenderBox>>,
RenderBoxContainerDefaultsMixin<RenderBox, ContainerBoxParentData<RenderBox>> { RenderBoxContainerDefaultsMixin<RenderBox, ContainerBoxParentData<RenderBox>> {
_RenderSegmentedControl({ _RenderSegmentedControl({
@required int selectedIndex, required int? selectedIndex,
@required int pressedIndex, required int? pressedIndex,
@required TextDirection textDirection, required TextDirection textDirection,
@required List<Color> backgroundColors, required List<Color> backgroundColors,
@required Color borderColor, required Color borderColor,
}) : assert(textDirection != null), }) : assert(textDirection != null),
_textDirection = textDirection, _textDirection = textDirection,
_selectedIndex = selectedIndex, _selectedIndex = selectedIndex,
...@@ -491,9 +489,9 @@ class _RenderSegmentedControl<T> extends RenderBox ...@@ -491,9 +489,9 @@ class _RenderSegmentedControl<T> extends RenderBox
_backgroundColors = backgroundColors, _backgroundColors = backgroundColors,
_borderColor = borderColor; _borderColor = borderColor;
int get selectedIndex => _selectedIndex; int? get selectedIndex => _selectedIndex;
int _selectedIndex; int? _selectedIndex;
set selectedIndex(int value) { set selectedIndex(int? value) {
if (_selectedIndex == value) { if (_selectedIndex == value) {
return; return;
} }
...@@ -501,9 +499,9 @@ class _RenderSegmentedControl<T> extends RenderBox ...@@ -501,9 +499,9 @@ class _RenderSegmentedControl<T> extends RenderBox
markNeedsPaint(); markNeedsPaint();
} }
int get pressedIndex => _pressedIndex; int? get pressedIndex => _pressedIndex;
int _pressedIndex; int? _pressedIndex;
set pressedIndex(int value) { set pressedIndex(int? value) {
if (_pressedIndex == value) { if (_pressedIndex == value) {
return; return;
} }
...@@ -543,7 +541,7 @@ class _RenderSegmentedControl<T> extends RenderBox ...@@ -543,7 +541,7 @@ class _RenderSegmentedControl<T> extends RenderBox
@override @override
double computeMinIntrinsicWidth(double height) { double computeMinIntrinsicWidth(double height) {
RenderBox child = firstChild; RenderBox? child = firstChild;
double minWidth = 0.0; double minWidth = 0.0;
while (child != null) { while (child != null) {
final _SegmentedControlContainerBoxParentData childParentData = child.parentData as _SegmentedControlContainerBoxParentData; final _SegmentedControlContainerBoxParentData childParentData = child.parentData as _SegmentedControlContainerBoxParentData;
...@@ -556,7 +554,7 @@ class _RenderSegmentedControl<T> extends RenderBox ...@@ -556,7 +554,7 @@ class _RenderSegmentedControl<T> extends RenderBox
@override @override
double computeMaxIntrinsicWidth(double height) { double computeMaxIntrinsicWidth(double height) {
RenderBox child = firstChild; RenderBox? child = firstChild;
double maxWidth = 0.0; double maxWidth = 0.0;
while (child != null) { while (child != null) {
final _SegmentedControlContainerBoxParentData childParentData = child.parentData as _SegmentedControlContainerBoxParentData; final _SegmentedControlContainerBoxParentData childParentData = child.parentData as _SegmentedControlContainerBoxParentData;
...@@ -569,7 +567,7 @@ class _RenderSegmentedControl<T> extends RenderBox ...@@ -569,7 +567,7 @@ class _RenderSegmentedControl<T> extends RenderBox
@override @override
double computeMinIntrinsicHeight(double width) { double computeMinIntrinsicHeight(double width) {
RenderBox child = firstChild; RenderBox? child = firstChild;
double minHeight = 0.0; double minHeight = 0.0;
while (child != null) { while (child != null) {
final _SegmentedControlContainerBoxParentData childParentData = child.parentData as _SegmentedControlContainerBoxParentData; final _SegmentedControlContainerBoxParentData childParentData = child.parentData as _SegmentedControlContainerBoxParentData;
...@@ -582,7 +580,7 @@ class _RenderSegmentedControl<T> extends RenderBox ...@@ -582,7 +580,7 @@ class _RenderSegmentedControl<T> extends RenderBox
@override @override
double computeMaxIntrinsicHeight(double width) { double computeMaxIntrinsicHeight(double width) {
RenderBox child = firstChild; RenderBox? child = firstChild;
double maxHeight = 0.0; double maxHeight = 0.0;
while (child != null) { while (child != null) {
final _SegmentedControlContainerBoxParentData childParentData = child.parentData as _SegmentedControlContainerBoxParentData; final _SegmentedControlContainerBoxParentData childParentData = child.parentData as _SegmentedControlContainerBoxParentData;
...@@ -594,7 +592,7 @@ class _RenderSegmentedControl<T> extends RenderBox ...@@ -594,7 +592,7 @@ class _RenderSegmentedControl<T> extends RenderBox
} }
@override @override
double computeDistanceToActualBaseline(TextBaseline baseline) { double? computeDistanceToActualBaseline(TextBaseline baseline) {
return defaultComputeDistanceToHighestActualBaseline(baseline); return defaultComputeDistanceToHighestActualBaseline(baseline);
} }
...@@ -605,8 +603,8 @@ class _RenderSegmentedControl<T> extends RenderBox ...@@ -605,8 +603,8 @@ class _RenderSegmentedControl<T> extends RenderBox
} }
} }
void _layoutRects(_NextChild nextChild, RenderBox leftChild, RenderBox rightChild) { void _layoutRects(_NextChild nextChild, RenderBox? leftChild, RenderBox? rightChild) {
RenderBox child = leftChild; RenderBox? child = leftChild;
double start = 0.0; double start = 0.0;
while (child != null) { while (child != null) {
final _SegmentedControlContainerBoxParentData childParentData = child.parentData as _SegmentedControlContainerBoxParentData; final _SegmentedControlContainerBoxParentData childParentData = child.parentData as _SegmentedControlContainerBoxParentData;
...@@ -640,7 +638,7 @@ class _RenderSegmentedControl<T> extends RenderBox ...@@ -640,7 +638,7 @@ class _RenderSegmentedControl<T> extends RenderBox
} }
childWidth = math.min(childWidth, constraints.maxWidth / childCount); childWidth = math.min(childWidth, constraints.maxWidth / childCount);
RenderBox child = firstChild; RenderBox? child = firstChild;
while (child != null) { while (child != null) {
final double boxHeight = child.getMaxIntrinsicHeight(childWidth); final double boxHeight = child.getMaxIntrinsicHeight(childWidth);
maxHeight = math.max(maxHeight, boxHeight); maxHeight = math.max(maxHeight, boxHeight);
...@@ -682,7 +680,7 @@ class _RenderSegmentedControl<T> extends RenderBox ...@@ -682,7 +680,7 @@ class _RenderSegmentedControl<T> extends RenderBox
@override @override
void paint(PaintingContext context, Offset offset) { void paint(PaintingContext context, Offset offset) {
RenderBox child = firstChild; RenderBox? child = firstChild;
int index = 0; int index = 0;
while (child != null) { while (child != null) {
_paintChild(context, offset, child, index); _paintChild(context, offset, child, index);
...@@ -697,13 +695,13 @@ class _RenderSegmentedControl<T> extends RenderBox ...@@ -697,13 +695,13 @@ class _RenderSegmentedControl<T> extends RenderBox
final _SegmentedControlContainerBoxParentData childParentData = child.parentData as _SegmentedControlContainerBoxParentData; final _SegmentedControlContainerBoxParentData childParentData = child.parentData as _SegmentedControlContainerBoxParentData;
context.canvas.drawRRect( context.canvas.drawRRect(
childParentData.surroundingRect.shift(offset), childParentData.surroundingRect!.shift(offset),
Paint() Paint()
..color = backgroundColors[childIndex] ..color = backgroundColors[childIndex]
..style = PaintingStyle.fill, ..style = PaintingStyle.fill,
); );
context.canvas.drawRRect( context.canvas.drawRRect(
childParentData.surroundingRect.shift(offset), childParentData.surroundingRect!.shift(offset),
Paint() Paint()
..color = borderColor ..color = borderColor
..strokeWidth = 1.0 ..strokeWidth = 1.0
...@@ -714,18 +712,18 @@ class _RenderSegmentedControl<T> extends RenderBox ...@@ -714,18 +712,18 @@ class _RenderSegmentedControl<T> extends RenderBox
} }
@override @override
bool hitTestChildren(BoxHitTestResult result, { @required Offset position }) { bool hitTestChildren(BoxHitTestResult result, { required Offset position }) {
assert(position != null); assert(position != null);
RenderBox child = lastChild; RenderBox? child = lastChild;
while (child != null) { while (child != null) {
final _SegmentedControlContainerBoxParentData childParentData = child.parentData as _SegmentedControlContainerBoxParentData; final _SegmentedControlContainerBoxParentData childParentData = child.parentData as _SegmentedControlContainerBoxParentData;
if (childParentData.surroundingRect.contains(position)) { if (childParentData.surroundingRect!.contains(position)) {
return result.addWithPaintOffset( return result.addWithPaintOffset(
offset: childParentData.offset, offset: childParentData.offset,
position: position, position: position,
hitTest: (BoxHitTestResult result, Offset localOffset) { hitTest: (BoxHitTestResult result, Offset localOffset) {
assert(localOffset == position - childParentData.offset); assert(localOffset == position - childParentData.offset);
return child.hitTest(result, position: localOffset); return child!.hitTest(result, position: localOffset);
}, },
); );
} }
......
...@@ -2,8 +2,6 @@ ...@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// @dart = 2.8
import 'dart:math' as math; import 'dart:math' as math;
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
...@@ -76,10 +74,10 @@ const Duration _kOpacityAnimationDuration = Duration(milliseconds: 470); ...@@ -76,10 +74,10 @@ const Duration _kOpacityAnimationDuration = Duration(milliseconds: 470);
const Duration _kHighlightAnimationDuration = Duration(milliseconds: 200); const Duration _kHighlightAnimationDuration = Duration(milliseconds: 200);
class _FontWeightTween extends Tween<FontWeight> { class _FontWeightTween extends Tween<FontWeight> {
_FontWeightTween({ FontWeight begin, FontWeight end }) : super(begin: begin, end: end); _FontWeightTween({ required FontWeight begin, required FontWeight end }) : super(begin: begin, end: end);
@override @override
FontWeight lerp(double t) => FontWeight.lerp(begin, end, t); FontWeight lerp(double t) => FontWeight.lerp(begin, end, t)!;
} }
/// An iOS 13 style segmented control. /// An iOS 13 style segmented control.
...@@ -140,9 +138,9 @@ class CupertinoSlidingSegmentedControl<T> extends StatefulWidget { ...@@ -140,9 +138,9 @@ class CupertinoSlidingSegmentedControl<T> extends StatefulWidget {
/// appear as selected. The [groupValue] must be either null or one of the keys /// appear as selected. The [groupValue] must be either null or one of the keys
/// in the [children] map. /// in the [children] map.
CupertinoSlidingSegmentedControl({ CupertinoSlidingSegmentedControl({
Key key, Key? key,
@required this.children, required this.children,
@required this.onValueChanged, required this.onValueChanged,
this.groupValue, this.groupValue,
this.thumbColor = _kThumbColor, this.thumbColor = _kThumbColor,
this.padding = _kHorizontalItemPadding, this.padding = _kHorizontalItemPadding,
...@@ -168,7 +166,7 @@ class CupertinoSlidingSegmentedControl<T> extends StatefulWidget { ...@@ -168,7 +166,7 @@ class CupertinoSlidingSegmentedControl<T> extends StatefulWidget {
/// ///
/// This must be one of the keys in the [Map] of [children]. /// This must be one of the keys in the [Map] of [children].
/// If this attribute is null, no widget will be initially selected. /// If this attribute is null, no widget will be initially selected.
final T groupValue; final T? groupValue;
/// The callback that is called when a new option is tapped. /// The callback that is called when a new option is tapped.
/// ///
...@@ -215,7 +213,7 @@ class CupertinoSlidingSegmentedControl<T> extends StatefulWidget { ...@@ -215,7 +213,7 @@ class CupertinoSlidingSegmentedControl<T> extends StatefulWidget {
/// } /// }
/// ``` /// ```
/// {@end-tool} /// {@end-tool}
final ValueChanged<T> onValueChanged; final ValueChanged<T?> onValueChanged;
/// The color used to paint the rounded rect behind the [children] and the separators. /// The color used to paint the rounded rect behind the [children] and the separators.
/// ///
...@@ -248,11 +246,11 @@ class _SegmentedControlState<T> extends State<CupertinoSlidingSegmentedControl<T ...@@ -248,11 +246,11 @@ class _SegmentedControlState<T> extends State<CupertinoSlidingSegmentedControl<T
final Map<T, AnimationController> _pressControllers = <T, AnimationController>{}; final Map<T, AnimationController> _pressControllers = <T, AnimationController>{};
final Tween<double> _pressTween = Tween<double>(begin: 1, end: 0.2); final Tween<double> _pressTween = Tween<double>(begin: 1, end: 0.2);
List<T> keys; late List<T> keys;
AnimationController thumbController; late AnimationController thumbController;
AnimationController separatorOpacityController; late AnimationController separatorOpacityController;
AnimationController thumbScaleController; late AnimationController thumbScaleController;
final TapGestureRecognizer tap = TapGestureRecognizer(); final TapGestureRecognizer tap = TapGestureRecognizer();
final HorizontalDragGestureRecognizer drag = HorizontalDragGestureRecognizer(); final HorizontalDragGestureRecognizer drag = HorizontalDragGestureRecognizer();
...@@ -320,8 +318,8 @@ class _SegmentedControlState<T> extends State<CupertinoSlidingSegmentedControl<T ...@@ -320,8 +318,8 @@ class _SegmentedControlState<T> extends State<CupertinoSlidingSegmentedControl<T
// Update animation controllers. // Update animation controllers.
for (final T oldKey in oldWidget.children.keys) { for (final T oldKey in oldWidget.children.keys) {
if (!widget.children.containsKey(oldKey)) { if (!widget.children.containsKey(oldKey)) {
_highlightControllers[oldKey].dispose(); _highlightControllers[oldKey]!.dispose();
_pressControllers[oldKey].dispose(); _pressControllers[oldKey]!.dispose();
_highlightControllers.remove(oldKey); _highlightControllers.remove(oldKey);
_pressControllers.remove(oldKey); _pressControllers.remove(oldKey);
...@@ -360,16 +358,16 @@ class _SegmentedControlState<T> extends State<CupertinoSlidingSegmentedControl<T ...@@ -360,16 +358,16 @@ class _SegmentedControlState<T> extends State<CupertinoSlidingSegmentedControl<T
} }
// Play highlight animation for the child located at _highlightControllers[at]. // Play highlight animation for the child located at _highlightControllers[at].
void _animateHighlightController({ T at, bool forward }) { void _animateHighlightController({ T? at, required bool forward }) {
if (at == null) if (at == null)
return; return;
final AnimationController controller = _highlightControllers[at]; final AnimationController? controller = _highlightControllers[at];
assert(!forward || controller != null); assert(!forward || controller != null);
controller?.animateTo(forward ? 1 : 0, duration: _kHighlightAnimationDuration, curve: Curves.ease); controller?.animateTo(forward ? 1 : 0, duration: _kHighlightAnimationDuration, curve: Curves.ease);
} }
T _highlighted; T? _highlighted;
set highlighted(T newValue) { set highlighted(T? newValue) {
if (_highlighted == newValue) if (_highlighted == newValue)
return; return;
_animateHighlightController(at: newValue, forward: true); _animateHighlightController(at: newValue, forward: true);
...@@ -377,8 +375,8 @@ class _SegmentedControlState<T> extends State<CupertinoSlidingSegmentedControl<T ...@@ -377,8 +375,8 @@ class _SegmentedControlState<T> extends State<CupertinoSlidingSegmentedControl<T
_highlighted = newValue; _highlighted = newValue;
} }
T _pressed; T? _pressed;
set pressed(T newValue) { set pressed(T? newValue) {
if (_pressed == newValue) if (_pressed == newValue)
return; return;
...@@ -386,7 +384,7 @@ class _SegmentedControlState<T> extends State<CupertinoSlidingSegmentedControl<T ...@@ -386,7 +384,7 @@ class _SegmentedControlState<T> extends State<CupertinoSlidingSegmentedControl<T
_pressControllers[_pressed]?.animateTo(0, duration: _kOpacityAnimationDuration, curve: Curves.ease); _pressControllers[_pressed]?.animateTo(0, duration: _kOpacityAnimationDuration, curve: Curves.ease);
} }
if (newValue != _highlighted && newValue != null) { if (newValue != _highlighted && newValue != null) {
_pressControllers[newValue].animateTo(1, duration: _kOpacityAnimationDuration, curve: Curves.ease); _pressControllers[newValue]!.animateTo(1, duration: _kOpacityAnimationDuration, curve: Curves.ease);
} }
_pressed = newValue; _pressed = newValue;
} }
...@@ -395,13 +393,13 @@ class _SegmentedControlState<T> extends State<CupertinoSlidingSegmentedControl<T ...@@ -395,13 +393,13 @@ class _SegmentedControlState<T> extends State<CupertinoSlidingSegmentedControl<T
widget.onValueChanged(_highlighted); widget.onValueChanged(_highlighted);
} }
T indexToKey(int index) => index == null ? null : keys[index]; T? indexToKey(int? index) => index == null ? null : keys[index];
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
debugCheckHasDirectionality(context); debugCheckHasDirectionality(context);
switch (Directionality.of(context)) { switch (Directionality.of(context)!) {
case TextDirection.ltr: case TextDirection.ltr:
keys = widget.children.keys.toList(growable: false); keys = widget.children.keys.toList(growable: false);
break; break;
...@@ -415,11 +413,11 @@ class _SegmentedControlState<T> extends State<CupertinoSlidingSegmentedControl<T ...@@ -415,11 +413,11 @@ class _SegmentedControlState<T> extends State<CupertinoSlidingSegmentedControl<T
..._highlightControllers.values, ..._highlightControllers.values,
..._pressControllers.values, ..._pressControllers.values,
]), ]),
builder: (BuildContext context, Widget child) { builder: (BuildContext context, Widget? child) {
final List<Widget> children = <Widget>[]; final List<Widget> children = <Widget>[];
for (final T currentKey in keys) { for (final T currentKey in keys) {
final TextStyle textStyle = DefaultTextStyle.of(context).style.copyWith( final TextStyle textStyle = DefaultTextStyle.of(context).style!.copyWith(
fontWeight: _highlightTween.evaluate(_highlightControllers[currentKey]), fontWeight: _highlightTween.evaluate(_highlightControllers[currentKey]!),
); );
final Widget child = DefaultTextStyle( final Widget child = DefaultTextStyle(
...@@ -430,7 +428,7 @@ class _SegmentedControlState<T> extends State<CupertinoSlidingSegmentedControl<T ...@@ -430,7 +428,7 @@ class _SegmentedControlState<T> extends State<CupertinoSlidingSegmentedControl<T
inMutuallyExclusiveGroup: true, inMutuallyExclusiveGroup: true,
selected: widget.groupValue == currentKey, selected: widget.groupValue == currentKey,
child: Opacity( child: Opacity(
opacity: _pressTween.evaluate(_pressControllers[currentKey]), opacity: _pressTween.evaluate(_pressControllers[currentKey]!),
// Expand the hitTest area to be as large as the Opacity widget. // Expand the hitTest area to be as large as the Opacity widget.
child: MetaData( child: MetaData(
behavior: HitTestBehavior.opaque, behavior: HitTestBehavior.opaque,
...@@ -443,7 +441,7 @@ class _SegmentedControlState<T> extends State<CupertinoSlidingSegmentedControl<T ...@@ -443,7 +441,7 @@ class _SegmentedControlState<T> extends State<CupertinoSlidingSegmentedControl<T
children.add(child); children.add(child);
} }
final int selectedIndex = widget.groupValue == null ? null : keys.indexOf(widget.groupValue); final int? selectedIndex = widget.groupValue == null ? null : keys.indexOf(widget.groupValue as T);
final Widget box = _SegmentedControlRenderWidget<T>( final Widget box = _SegmentedControlRenderWidget<T>(
children: children, children: children,
...@@ -470,15 +468,15 @@ class _SegmentedControlState<T> extends State<CupertinoSlidingSegmentedControl<T ...@@ -470,15 +468,15 @@ class _SegmentedControlState<T> extends State<CupertinoSlidingSegmentedControl<T
class _SegmentedControlRenderWidget<T> extends MultiChildRenderObjectWidget { class _SegmentedControlRenderWidget<T> extends MultiChildRenderObjectWidget {
_SegmentedControlRenderWidget({ _SegmentedControlRenderWidget({
Key key, Key? key,
List<Widget> children = const <Widget>[], List<Widget> children = const <Widget>[],
@required this.selectedIndex, required this.selectedIndex,
@required this.thumbColor, required this.thumbColor,
@required this.state, required this.state,
}) : super(key: key, children: children); }) : super(key: key, children: children);
final int selectedIndex; final int? selectedIndex;
final Color thumbColor; final Color? thumbColor;
final _SegmentedControlState<T> state; final _SegmentedControlState<T> state;
@override @override
...@@ -501,7 +499,7 @@ class _SegmentedControlRenderWidget<T> extends MultiChildRenderObjectWidget { ...@@ -501,7 +499,7 @@ class _SegmentedControlRenderWidget<T> extends MultiChildRenderObjectWidget {
class _ChildAnimationManifest { class _ChildAnimationManifest {
_ChildAnimationManifest({ _ChildAnimationManifest({
this.opacity = 1, this.opacity = 1,
@required this.separatorOpacity, required this.separatorOpacity,
}) : assert(separatorOpacity != null), }) : assert(separatorOpacity != null),
assert(opacity != null), assert(opacity != null),
separatorTween = Tween<double>(begin: separatorOpacity, end: separatorOpacity), separatorTween = Tween<double>(begin: separatorOpacity, end: separatorOpacity),
...@@ -550,9 +548,9 @@ class _RenderSegmentedControl<T> extends RenderBox ...@@ -550,9 +548,9 @@ class _RenderSegmentedControl<T> extends RenderBox
with ContainerRenderObjectMixin<RenderBox, ContainerBoxParentData<RenderBox>>, with ContainerRenderObjectMixin<RenderBox, ContainerBoxParentData<RenderBox>>,
RenderBoxContainerDefaultsMixin<RenderBox, ContainerBoxParentData<RenderBox>> { RenderBoxContainerDefaultsMixin<RenderBox, ContainerBoxParentData<RenderBox>> {
_RenderSegmentedControl({ _RenderSegmentedControl({
@required int selectedIndex, required int? selectedIndex,
@required Color thumbColor, required Color? thumbColor,
@required this.state, required this.state,
}) : _highlightedIndex = selectedIndex, }) : _highlightedIndex = selectedIndex,
_thumbColor = thumbColor, _thumbColor = thumbColor,
assert(state != null) { assert(state != null) {
...@@ -569,29 +567,29 @@ class _RenderSegmentedControl<T> extends RenderBox ...@@ -569,29 +567,29 @@ class _RenderSegmentedControl<T> extends RenderBox
final _SegmentedControlState<T> state; final _SegmentedControlState<T> state;
Map<RenderBox, _ChildAnimationManifest> _childAnimations = <RenderBox, _ChildAnimationManifest>{}; Map<RenderBox, _ChildAnimationManifest>? _childAnimations = <RenderBox, _ChildAnimationManifest>{};
// The current **Unscaled** Thumb Rect. // The current **Unscaled** Thumb Rect.
Rect currentThumbRect; Rect? currentThumbRect;
Tween<Rect> _currentThumbTween; Tween<Rect?>? _currentThumbTween;
Tween<double> _thumbScaleTween = Tween<double>(begin: _kMinThumbScale, end: 1); Tween<double> _thumbScaleTween = Tween<double>(begin: _kMinThumbScale, end: 1);
double currentThumbScale = 1; double currentThumbScale = 1;
// The current position of the active drag pointer. // The current position of the active drag pointer.
Offset _localDragOffset; Offset? _localDragOffset;
// Whether the current drag gesture started on a selected segment. // Whether the current drag gesture started on a selected segment.
bool _startedOnSelectedSegment; bool? _startedOnSelectedSegment;
@override @override
void insert(RenderBox child, { RenderBox after }) { void insert(RenderBox child, { RenderBox? after }) {
super.insert(child, after: after); super.insert(child, after: after);
if (_childAnimations == null) if (_childAnimations == null)
return; return;
assert(_childAnimations[child] == null); assert(_childAnimations![child] == null);
_childAnimations[child] = _ChildAnimationManifest(separatorOpacity: 1); _childAnimations![child] = _ChildAnimationManifest(separatorOpacity: 1);
} }
@override @override
...@@ -620,9 +618,9 @@ class _RenderSegmentedControl<T> extends RenderBox ...@@ -620,9 +618,9 @@ class _RenderSegmentedControl<T> extends RenderBox
// when true some animation tweens will be updated in paint phase. // when true some animation tweens will be updated in paint phase.
bool _needsThumbAnimationUpdate = false; bool _needsThumbAnimationUpdate = false;
int get highlightedIndex => _highlightedIndex; int? get highlightedIndex => _highlightedIndex;
int _highlightedIndex; int? _highlightedIndex;
set highlightedIndex(int value) { set highlightedIndex(int? value) {
if (_highlightedIndex == value) { if (_highlightedIndex == value) {
return; return;
} }
...@@ -644,16 +642,16 @@ class _RenderSegmentedControl<T> extends RenderBox ...@@ -644,16 +642,16 @@ class _RenderSegmentedControl<T> extends RenderBox
markNeedsSemanticsUpdate(); markNeedsSemanticsUpdate();
} }
void guardedSetHighlightedIndex(int value) { void guardedSetHighlightedIndex(int? value) {
// Ignore set highlightedIndex when the user is dragging the thumb around. // Ignore set highlightedIndex when the user is dragging the thumb around.
if (_startedOnSelectedSegment == true) if (_startedOnSelectedSegment == true)
return; return;
highlightedIndex = value; highlightedIndex = value;
} }
int get pressedIndex => _pressedIndex; int? get pressedIndex => _pressedIndex;
int _pressedIndex; int? _pressedIndex;
set pressedIndex(int value) { set pressedIndex(int? value) {
if (_pressedIndex == value) { if (_pressedIndex == value) {
return; return;
} }
...@@ -664,9 +662,9 @@ class _RenderSegmentedControl<T> extends RenderBox ...@@ -664,9 +662,9 @@ class _RenderSegmentedControl<T> extends RenderBox
state.pressed = state.indexToKey(value); state.pressed = state.indexToKey(value);
} }
Color get thumbColor => _thumbColor; Color? get thumbColor => _thumbColor;
Color _thumbColor; Color? _thumbColor;
set thumbColor(Color value) { set thumbColor(Color? value) {
if (_thumbColor == value) { if (_thumbColor == value) {
return; return;
} }
...@@ -686,13 +684,13 @@ class _RenderSegmentedControl<T> extends RenderBox ...@@ -686,13 +684,13 @@ class _RenderSegmentedControl<T> extends RenderBox
} }
} }
int indexFromLocation(Offset location) { int? indexFromLocation(Offset location) {
return childCount == 0 return childCount == 0
? null ? null
// This assumes all children have the same width. // This assumes all children have the same width.
: ((location.dx / (size.width / childCount)) : (location.dx / (size.width / childCount))
.floor() .floor()
.clamp(0, childCount - 1) as int); .clamp(0, childCount - 1);
} }
void _onTapUp(TapUpDetails details) { void _onTapUp(TapUpDetails details) {
...@@ -703,20 +701,20 @@ class _RenderSegmentedControl<T> extends RenderBox ...@@ -703,20 +701,20 @@ class _RenderSegmentedControl<T> extends RenderBox
void _onDown(DragDownDetails details) { void _onDown(DragDownDetails details) {
assert(size.contains(details.localPosition)); assert(size.contains(details.localPosition));
_localDragOffset = details.localPosition; _localDragOffset = details.localPosition;
final int index = indexFromLocation(_localDragOffset); final int? index = indexFromLocation(_localDragOffset!);
_startedOnSelectedSegment = index == highlightedIndex; _startedOnSelectedSegment = index == highlightedIndex;
pressedIndex = index; pressedIndex = index;
if (_startedOnSelectedSegment) { if (_startedOnSelectedSegment!) {
_playThumbScaleAnimation(isExpanding: false); _playThumbScaleAnimation(isExpanding: false);
} }
} }
void _onUpdate(DragUpdateDetails details) { void _onUpdate(DragUpdateDetails details) {
_localDragOffset = details.localPosition; _localDragOffset = details.localPosition;
final int newIndex = indexFromLocation(_localDragOffset); final int? newIndex = indexFromLocation(_localDragOffset!);
if (_startedOnSelectedSegment) { if (_startedOnSelectedSegment!) {
highlightedIndex = newIndex; highlightedIndex = newIndex;
pressedIndex = newIndex; pressedIndex = newIndex;
} else { } else {
...@@ -725,7 +723,7 @@ class _RenderSegmentedControl<T> extends RenderBox ...@@ -725,7 +723,7 @@ class _RenderSegmentedControl<T> extends RenderBox
} }
void _onEnd(DragEndDetails details) { void _onEnd(DragEndDetails details) {
if (_startedOnSelectedSegment) { if (_startedOnSelectedSegment!) {
_playThumbScaleAnimation(isExpanding: true); _playThumbScaleAnimation(isExpanding: true);
state.didChangeSelectedViaGesture(); state.didChangeSelectedViaGesture();
} }
...@@ -740,7 +738,7 @@ class _RenderSegmentedControl<T> extends RenderBox ...@@ -740,7 +738,7 @@ class _RenderSegmentedControl<T> extends RenderBox
} }
void _onCancel() { void _onCancel() {
if (_startedOnSelectedSegment) { if (_startedOnSelectedSegment!) {
_playThumbScaleAnimation(isExpanding: true); _playThumbScaleAnimation(isExpanding: true);
} }
...@@ -749,7 +747,7 @@ class _RenderSegmentedControl<T> extends RenderBox ...@@ -749,7 +747,7 @@ class _RenderSegmentedControl<T> extends RenderBox
_startedOnSelectedSegment = null; _startedOnSelectedSegment = null;
} }
void _playThumbScaleAnimation({ @required bool isExpanding }) { void _playThumbScaleAnimation({ required bool isExpanding }) {
assert(isExpanding != null); assert(isExpanding != null);
_thumbScaleTween = Tween<double>(begin: currentThumbScale, end: isExpanding ? 1 : _kMinThumbScale); _thumbScaleTween = Tween<double>(begin: currentThumbScale, end: isExpanding ? 1 : _kMinThumbScale);
state.thumbScaleController.animateWith(_kThumbSpringAnimationSimulation); state.thumbScaleController.animateWith(_kThumbSpringAnimationSimulation);
...@@ -762,7 +760,7 @@ class _RenderSegmentedControl<T> extends RenderBox ...@@ -762,7 +760,7 @@ class _RenderSegmentedControl<T> extends RenderBox
@override @override
double computeMinIntrinsicWidth(double height) { double computeMinIntrinsicWidth(double height) {
RenderBox child = firstChild; RenderBox? child = firstChild;
double maxMinChildWidth = 0; double maxMinChildWidth = 0;
while (child != null) { while (child != null) {
final _SegmentedControlContainerBoxParentData childParentData = final _SegmentedControlContainerBoxParentData childParentData =
...@@ -776,7 +774,7 @@ class _RenderSegmentedControl<T> extends RenderBox ...@@ -776,7 +774,7 @@ class _RenderSegmentedControl<T> extends RenderBox
@override @override
double computeMaxIntrinsicWidth(double height) { double computeMaxIntrinsicWidth(double height) {
RenderBox child = firstChild; RenderBox? child = firstChild;
double maxMaxChildWidth = 0; double maxMaxChildWidth = 0;
while (child != null) { while (child != null) {
final _SegmentedControlContainerBoxParentData childParentData = final _SegmentedControlContainerBoxParentData childParentData =
...@@ -790,7 +788,7 @@ class _RenderSegmentedControl<T> extends RenderBox ...@@ -790,7 +788,7 @@ class _RenderSegmentedControl<T> extends RenderBox
@override @override
double computeMinIntrinsicHeight(double width) { double computeMinIntrinsicHeight(double width) {
RenderBox child = firstChild; RenderBox? child = firstChild;
double maxMinChildHeight = 0; double maxMinChildHeight = 0;
while (child != null) { while (child != null) {
final _SegmentedControlContainerBoxParentData childParentData = final _SegmentedControlContainerBoxParentData childParentData =
...@@ -804,7 +802,7 @@ class _RenderSegmentedControl<T> extends RenderBox ...@@ -804,7 +802,7 @@ class _RenderSegmentedControl<T> extends RenderBox
@override @override
double computeMaxIntrinsicHeight(double width) { double computeMaxIntrinsicHeight(double width) {
RenderBox child = firstChild; RenderBox? child = firstChild;
double maxMaxChildHeight = 0; double maxMaxChildHeight = 0;
while (child != null) { while (child != null) {
final _SegmentedControlContainerBoxParentData childParentData = final _SegmentedControlContainerBoxParentData childParentData =
...@@ -817,7 +815,7 @@ class _RenderSegmentedControl<T> extends RenderBox ...@@ -817,7 +815,7 @@ class _RenderSegmentedControl<T> extends RenderBox
} }
@override @override
double computeDistanceToActualBaseline(TextBaseline baseline) { double? computeDistanceToActualBaseline(TextBaseline baseline) {
return defaultComputeDistanceToHighestActualBaseline(baseline); return defaultComputeDistanceToHighestActualBaseline(baseline);
} }
...@@ -843,7 +841,7 @@ class _RenderSegmentedControl<T> extends RenderBox ...@@ -843,7 +841,7 @@ class _RenderSegmentedControl<T> extends RenderBox
(constraints.maxWidth - totalSeparatorWidth) / childCount, (constraints.maxWidth - totalSeparatorWidth) / childCount,
); );
RenderBox child = firstChild; RenderBox? child = firstChild;
while (child != null) { while (child != null) {
final double boxHeight = child.getMaxIntrinsicHeight(childWidth); final double boxHeight = child.getMaxIntrinsicHeight(childWidth);
maxHeight = math.max(maxHeight, boxHeight); maxHeight = math.max(maxHeight, boxHeight);
...@@ -890,13 +888,13 @@ class _RenderSegmentedControl<T> extends RenderBox ...@@ -890,13 +888,13 @@ class _RenderSegmentedControl<T> extends RenderBox
for (int i = 0; i < childCount - 1; i += 1) { for (int i = 0; i < childCount - 1; i += 1) {
// The separator associated with the last child will not be painted (unless // The separator associated with the last child will not be painted (unless
// a new trailing segment is added), and its opacity will always be 1. // a new trailing segment is added), and its opacity will always be 1.
final bool shouldFadeOut = i == highlightedIndex || i == highlightedIndex - 1; final bool shouldFadeOut = i == highlightedIndex || i == highlightedIndex! - 1;
final RenderBox child = children[i]; final RenderBox child = children[i];
_childAnimations[child] = _ChildAnimationManifest(separatorOpacity: shouldFadeOut ? 0 : 1); _childAnimations![child] = _ChildAnimationManifest(separatorOpacity: shouldFadeOut ? 0 : 1);
} }
} }
final RenderBox selectedChild = children[highlightedIndex]; final RenderBox selectedChild = children[highlightedIndex!];
final _SegmentedControlContainerBoxParentData childParentData = final _SegmentedControlContainerBoxParentData childParentData =
selectedChild.parentData as _SegmentedControlContainerBoxParentData; selectedChild.parentData as _SegmentedControlContainerBoxParentData;
...@@ -910,9 +908,9 @@ class _RenderSegmentedControl<T> extends RenderBox ...@@ -910,9 +908,9 @@ class _RenderSegmentedControl<T> extends RenderBox
for (int i = 0; i < childCount - 1; i += 1) { for (int i = 0; i < childCount - 1; i += 1) {
// The separator associated with the last child will not be painted (unless // The separator associated with the last child will not be painted (unless
// a new segment is appended to the child list), and its opacity will always be 1. // a new segment is appended to the child list), and its opacity will always be 1.
final bool shouldFadeOut = i == highlightedIndex || i == highlightedIndex - 1; final bool shouldFadeOut = i == highlightedIndex || i == highlightedIndex! - 1;
final RenderBox child = children[i]; final RenderBox child = children[i];
final _ChildAnimationManifest manifest = _childAnimations[child]; final _ChildAnimationManifest manifest = _childAnimations![child]!;
assert(manifest != null); assert(manifest != null);
manifest.separatorTween = Tween<double>( manifest.separatorTween = Tween<double>(
begin: manifest.separatorOpacity, begin: manifest.separatorOpacity,
...@@ -921,8 +919,8 @@ class _RenderSegmentedControl<T> extends RenderBox ...@@ -921,8 +919,8 @@ class _RenderSegmentedControl<T> extends RenderBox
} }
_needsThumbAnimationUpdate = false; _needsThumbAnimationUpdate = false;
} else if (_currentThumbTween != null && unscaledThumbTargetRect != _currentThumbTween.begin) { } else if (_currentThumbTween != null && unscaledThumbTargetRect != _currentThumbTween!.begin) {
_currentThumbTween = RectTween(begin: _currentThumbTween.begin, end: unscaledThumbTargetRect); _currentThumbTween = RectTween(begin: _currentThumbTween!.begin, end: unscaledThumbTargetRect);
} }
for (int index = 0; index < childCount - 1; index += 1) { for (int index = 0; index < childCount - 1; index += 1) {
...@@ -935,9 +933,9 @@ class _RenderSegmentedControl<T> extends RenderBox ...@@ -935,9 +933,9 @@ class _RenderSegmentedControl<T> extends RenderBox
currentThumbScale = _thumbScaleTween.evaluate(state.thumbScaleController); currentThumbScale = _thumbScaleTween.evaluate(state.thumbScaleController);
final Rect thumbRect = Rect.fromCenter( final Rect thumbRect = Rect.fromCenter(
center: currentThumbRect.center, center: currentThumbRect!.center,
width: currentThumbRect.width * currentThumbScale, width: currentThumbRect!.width * currentThumbScale,
height: currentThumbRect.height * currentThumbScale, height: currentThumbRect!.height * currentThumbScale,
); );
_paintThumb(context, offset, thumbRect); _paintThumb(context, offset, thumbRect);
...@@ -964,8 +962,8 @@ class _RenderSegmentedControl<T> extends RenderBox ...@@ -964,8 +962,8 @@ class _RenderSegmentedControl<T> extends RenderBox
final Paint paint = Paint(); final Paint paint = Paint();
final _ChildAnimationManifest manifest = _childAnimations == null ? null : _childAnimations[child]; final _ChildAnimationManifest? manifest = _childAnimations == null ? null : _childAnimations![child];
final double opacity = manifest?.separatorTween?.evaluate(state.separatorOpacityController) ?? 1; final double opacity = manifest?.separatorTween.evaluate(state.separatorOpacityController) ?? 1;
manifest?.separatorOpacity = opacity; manifest?.separatorOpacity = opacity;
paint.color = _kSeparatorColor.withOpacity(_kSeparatorColor.opacity * opacity); paint.color = _kSeparatorColor.withOpacity(_kSeparatorColor.opacity * opacity);
...@@ -1015,14 +1013,14 @@ class _RenderSegmentedControl<T> extends RenderBox ...@@ -1015,14 +1013,14 @@ class _RenderSegmentedControl<T> extends RenderBox
context.canvas.drawRRect( context.canvas.drawRRect(
thumbRRect, thumbRRect,
Paint()..color = thumbColor, Paint()..color = thumbColor!,
); );
} }
@override @override
bool hitTestChildren(BoxHitTestResult result, { @required Offset position }) { bool hitTestChildren(BoxHitTestResult result, { required Offset position }) {
assert(position != null); assert(position != null);
RenderBox child = lastChild; RenderBox? child = lastChild;
while (child != null) { while (child != null) {
final _SegmentedControlContainerBoxParentData childParentData = final _SegmentedControlContainerBoxParentData childParentData =
child.parentData as _SegmentedControlContainerBoxParentData; child.parentData as _SegmentedControlContainerBoxParentData;
...@@ -1032,7 +1030,7 @@ class _RenderSegmentedControl<T> extends RenderBox ...@@ -1032,7 +1030,7 @@ class _RenderSegmentedControl<T> extends RenderBox
position: position, position: position,
hitTest: (BoxHitTestResult result, Offset localOffset) { hitTest: (BoxHitTestResult result, Offset localOffset) {
assert(localOffset == position - childParentData.offset); assert(localOffset == position - childParentData.offset);
return child.hitTest(result, position: localOffset); return child!.hitTest(result, position: localOffset);
}, },
); );
} }
......
...@@ -2,8 +2,6 @@ ...@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// @dart = 2.8
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'bottom_tab_bar.dart'; import 'bottom_tab_bar.dart';
...@@ -207,9 +205,9 @@ class CupertinoTabScaffold extends StatefulWidget { ...@@ -207,9 +205,9 @@ class CupertinoTabScaffold extends StatefulWidget {
/// ///
/// The [tabBar] and [tabBuilder] arguments must not be null. /// The [tabBar] and [tabBuilder] arguments must not be null.
CupertinoTabScaffold({ CupertinoTabScaffold({
Key key, Key? key,
@required this.tabBar, required this.tabBar,
@required this.tabBuilder, required this.tabBuilder,
this.controller, this.controller,
this.backgroundColor, this.backgroundColor,
this.resizeToAvoidBottomInset = true, this.resizeToAvoidBottomInset = true,
...@@ -258,7 +256,7 @@ class CupertinoTabScaffold extends StatefulWidget { ...@@ -258,7 +256,7 @@ class CupertinoTabScaffold extends StatefulWidget {
/// index value. /// index value.
/// ///
/// Defaults to null. /// Defaults to null.
final CupertinoTabController controller; final CupertinoTabController? controller;
/// An [IndexedWidgetBuilder] that's called when tabs become active. /// An [IndexedWidgetBuilder] that's called when tabs become active.
/// ///
...@@ -280,7 +278,7 @@ class CupertinoTabScaffold extends StatefulWidget { ...@@ -280,7 +278,7 @@ class CupertinoTabScaffold extends StatefulWidget {
/// The color of the widget that underlies the entire scaffold. /// The color of the widget that underlies the entire scaffold.
/// ///
/// By default uses [CupertinoTheme]'s `scaffoldBackgroundColor` when null. /// By default uses [CupertinoTheme]'s `scaffoldBackgroundColor` when null.
final Color backgroundColor; final Color? backgroundColor;
/// Whether the body should size itself to avoid the window's bottom inset. /// Whether the body should size itself to avoid the window's bottom inset.
/// ///
...@@ -296,7 +294,7 @@ class CupertinoTabScaffold extends StatefulWidget { ...@@ -296,7 +294,7 @@ class CupertinoTabScaffold extends StatefulWidget {
} }
class _CupertinoTabScaffoldState extends State<CupertinoTabScaffold> { class _CupertinoTabScaffoldState extends State<CupertinoTabScaffold> {
CupertinoTabController _controller; CupertinoTabController? _controller;
@override @override
void initState() { void initState() {
...@@ -317,7 +315,7 @@ class _CupertinoTabScaffoldState extends State<CupertinoTabScaffold> { ...@@ -317,7 +315,7 @@ class _CupertinoTabScaffoldState extends State<CupertinoTabScaffold> {
if (shouldDisposeOldController) { if (shouldDisposeOldController) {
_controller?.dispose(); _controller?.dispose();
} else if (_controller?._isDisposed == false) { } else if (_controller?._isDisposed == false) {
_controller.removeListener(_onCurrentIndexChange); _controller!.removeListener(_onCurrentIndexChange);
} }
newController.addListener(_onCurrentIndexChange); newController.addListener(_onCurrentIndexChange);
...@@ -326,8 +324,8 @@ class _CupertinoTabScaffoldState extends State<CupertinoTabScaffold> { ...@@ -326,8 +324,8 @@ class _CupertinoTabScaffoldState extends State<CupertinoTabScaffold> {
void _onCurrentIndexChange() { void _onCurrentIndexChange() {
assert( assert(
_controller.index >= 0 && _controller.index < widget.tabBar.items.length, _controller!.index >= 0 && _controller!.index < widget.tabBar.items.length,
"The $runtimeType's current index ${_controller.index} is " "The $runtimeType's current index ${_controller!.index} is "
'out of bounds for the tab bar with ${widget.tabBar.items.length} tabs' 'out of bounds for the tab bar with ${widget.tabBar.items.length} tabs'
); );
...@@ -341,20 +339,20 @@ class _CupertinoTabScaffoldState extends State<CupertinoTabScaffold> { ...@@ -341,20 +339,20 @@ class _CupertinoTabScaffoldState extends State<CupertinoTabScaffold> {
super.didUpdateWidget(oldWidget); super.didUpdateWidget(oldWidget);
if (widget.controller != oldWidget.controller) { if (widget.controller != oldWidget.controller) {
_updateTabController(shouldDisposeOldController: oldWidget.controller == null); _updateTabController(shouldDisposeOldController: oldWidget.controller == null);
} else if (_controller.index >= widget.tabBar.items.length) { } else if (_controller!.index >= widget.tabBar.items.length) {
// If a new [tabBar] with less than (_controller.index + 1) items is provided, // If a new [tabBar] with less than (_controller.index + 1) items is provided,
// clamp the current index. // clamp the current index.
_controller.index = widget.tabBar.items.length - 1; _controller!.index = widget.tabBar.items.length - 1;
} }
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final MediaQueryData existingMediaQuery = MediaQuery.of(context); final MediaQueryData existingMediaQuery = MediaQuery.of(context)!;
MediaQueryData newMediaQuery = MediaQuery.of(context); MediaQueryData newMediaQuery = MediaQuery.of(context)!;
Widget content = _TabSwitchingView( Widget content = _TabSwitchingView(
currentTabIndex: _controller.index, currentTabIndex: _controller!.index,
tabCount: widget.tabBar.items.length, tabCount: widget.tabBar.items.length,
tabBuilder: widget.tabBuilder, tabBuilder: widget.tabBuilder,
); );
...@@ -417,12 +415,11 @@ class _CupertinoTabScaffoldState extends State<CupertinoTabScaffold> { ...@@ -417,12 +415,11 @@ class _CupertinoTabScaffoldState extends State<CupertinoTabScaffold> {
// our own listener to update the [_controller.currentIndex] on top of a possibly user // our own listener to update the [_controller.currentIndex] on top of a possibly user
// provided callback. // provided callback.
child: widget.tabBar.copyWith( child: widget.tabBar.copyWith(
currentIndex: _controller.index, currentIndex: _controller!.index,
onTap: (int newIndex) { onTap: (int newIndex) {
_controller.index = newIndex; _controller!.index = newIndex;
// Chain the user's original callback. // Chain the user's original callback.
if (widget.tabBar.onTap != null) widget.tabBar.onTap?.call(newIndex);
widget.tabBar.onTap(newIndex);
}, },
), ),
), ),
...@@ -438,7 +435,7 @@ class _CupertinoTabScaffoldState extends State<CupertinoTabScaffold> { ...@@ -438,7 +435,7 @@ class _CupertinoTabScaffoldState extends State<CupertinoTabScaffold> {
if (widget.controller == null) { if (widget.controller == null) {
_controller?.dispose(); _controller?.dispose();
} else if (_controller?._isDisposed == false) { } else if (_controller?._isDisposed == false) {
_controller.removeListener(_onCurrentIndexChange); _controller!.removeListener(_onCurrentIndexChange);
} }
super.dispose(); super.dispose();
...@@ -449,9 +446,9 @@ class _CupertinoTabScaffoldState extends State<CupertinoTabScaffold> { ...@@ -449,9 +446,9 @@ class _CupertinoTabScaffoldState extends State<CupertinoTabScaffold> {
/// at a time and on stage. Off stage tabs' animations are stopped. /// at a time and on stage. Off stage tabs' animations are stopped.
class _TabSwitchingView extends StatefulWidget { class _TabSwitchingView extends StatefulWidget {
const _TabSwitchingView({ const _TabSwitchingView({
@required this.currentTabIndex, required this.currentTabIndex,
@required this.tabCount, required this.tabCount,
@required this.tabBuilder, required this.tabBuilder,
}) : assert(currentTabIndex != null), }) : assert(currentTabIndex != null),
assert(tabCount != null && tabCount > 0), assert(tabCount != null && tabCount > 0),
assert(tabBuilder != null); assert(tabBuilder != null);
......
...@@ -2,8 +2,6 @@ ...@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// @dart = 2.8
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'app.dart' show CupertinoApp; import 'app.dart' show CupertinoApp;
...@@ -43,7 +41,7 @@ import 'route.dart'; ...@@ -43,7 +41,7 @@ import 'route.dart';
class CupertinoTabView extends StatefulWidget { class CupertinoTabView extends StatefulWidget {
/// Creates the content area for a tab in a [CupertinoTabScaffold]. /// Creates the content area for a tab in a [CupertinoTabScaffold].
const CupertinoTabView({ const CupertinoTabView({
Key key, Key? key,
this.builder, this.builder,
this.navigatorKey, this.navigatorKey,
this.defaultTitle, this.defaultTitle,
...@@ -68,7 +66,7 @@ class CupertinoTabView extends StatefulWidget { ...@@ -68,7 +66,7 @@ class CupertinoTabView extends StatefulWidget {
/// * Calling [State.setState] on a descendant [StatefulWidget]'s [State] /// * Calling [State.setState] on a descendant [StatefulWidget]'s [State]
/// * Modifying an [InheritedWidget] that a descendant registered itself /// * Modifying an [InheritedWidget] that a descendant registered itself
/// as a dependent to. /// as a dependent to.
final WidgetBuilder builder; final WidgetBuilder? builder;
/// A key to use when building this widget's [Navigator]. /// A key to use when building this widget's [Navigator].
/// ///
...@@ -81,10 +79,10 @@ class CupertinoTabView extends StatefulWidget { ...@@ -81,10 +79,10 @@ class CupertinoTabView extends StatefulWidget {
/// tab's state in the process; in that case, the [navigatorObservers] /// tab's state in the process; in that case, the [navigatorObservers]
/// must also be changed, since the previous observers will be attached to the /// must also be changed, since the previous observers will be attached to the
/// previous navigator. /// previous navigator.
final GlobalKey<NavigatorState> navigatorKey; final GlobalKey<NavigatorState>? navigatorKey;
/// The title of the default route. /// The title of the default route.
final String defaultTitle; final String? defaultTitle;
/// This tab view's routing table. /// This tab view's routing table.
/// ///
...@@ -105,12 +103,12 @@ class CupertinoTabView extends StatefulWidget { ...@@ -105,12 +103,12 @@ class CupertinoTabView extends StatefulWidget {
/// ///
/// This routing table is not shared with any routing tables of ancestor or /// This routing table is not shared with any routing tables of ancestor or
/// descendant [Navigator]s. /// descendant [Navigator]s.
final Map<String, WidgetBuilder> routes; final Map<String, WidgetBuilder>? routes;
/// The route generator callback used when the tab view is navigated to a named route. /// The route generator callback used when the tab view is navigated to a named route.
/// ///
/// This is used if [routes] does not contain the requested route. /// This is used if [routes] does not contain the requested route.
final RouteFactory onGenerateRoute; final RouteFactory? onGenerateRoute;
/// Called when [onGenerateRoute] also fails to generate a route. /// Called when [onGenerateRoute] also fails to generate a route.
/// ///
...@@ -120,7 +118,7 @@ class CupertinoTabView extends StatefulWidget { ...@@ -120,7 +118,7 @@ class CupertinoTabView extends StatefulWidget {
/// ///
/// The default implementation pushes a route that displays an ugly error /// The default implementation pushes a route that displays an ugly error
/// message. /// message.
final RouteFactory onUnknownRoute; final RouteFactory? onUnknownRoute;
/// The list of observers for the [Navigator] created in this tab view. /// The list of observers for the [Navigator] created in this tab view.
/// ///
...@@ -134,8 +132,8 @@ class CupertinoTabView extends StatefulWidget { ...@@ -134,8 +132,8 @@ class CupertinoTabView extends StatefulWidget {
} }
class _CupertinoTabViewState extends State<CupertinoTabView> { class _CupertinoTabViewState extends State<CupertinoTabView> {
HeroController _heroController; late HeroController _heroController;
List<NavigatorObserver> _navigatorObservers; late List<NavigatorObserver> _navigatorObservers;
@override @override
void initState() { void initState() {
...@@ -169,15 +167,15 @@ class _CupertinoTabViewState extends State<CupertinoTabView> { ...@@ -169,15 +167,15 @@ class _CupertinoTabViewState extends State<CupertinoTabView> {
); );
} }
Route<dynamic> _onGenerateRoute(RouteSettings settings) { Route<dynamic>? _onGenerateRoute(RouteSettings settings) {
final String name = settings.name; final String? name = settings.name;
WidgetBuilder routeBuilder; WidgetBuilder? routeBuilder;
String title; String? title;
if (name == Navigator.defaultRouteName && widget.builder != null) { if (name == Navigator.defaultRouteName && widget.builder != null) {
routeBuilder = widget.builder; routeBuilder = widget.builder!;
title = widget.defaultTitle; title = widget.defaultTitle;
} else if (widget.routes != null) { } else if (widget.routes != null) {
routeBuilder = widget.routes[name]; routeBuilder = widget.routes![name];
} }
if (routeBuilder != null) { if (routeBuilder != null) {
return CupertinoPageRoute<dynamic>( return CupertinoPageRoute<dynamic>(
...@@ -187,11 +185,11 @@ class _CupertinoTabViewState extends State<CupertinoTabView> { ...@@ -187,11 +185,11 @@ class _CupertinoTabViewState extends State<CupertinoTabView> {
); );
} }
if (widget.onGenerateRoute != null) if (widget.onGenerateRoute != null)
return widget.onGenerateRoute(settings); return widget.onGenerateRoute!(settings);
return null; return null;
} }
Route<dynamic> _onUnknownRoute(RouteSettings settings) { Route<dynamic>? _onUnknownRoute(RouteSettings settings) {
assert(() { assert(() {
if (widget.onUnknownRoute == null) { if (widget.onUnknownRoute == null) {
throw FlutterError( throw FlutterError(
...@@ -208,7 +206,7 @@ class _CupertinoTabViewState extends State<CupertinoTabView> { ...@@ -208,7 +206,7 @@ class _CupertinoTabViewState extends State<CupertinoTabView> {
} }
return true; return true;
}()); }());
final Route<dynamic> result = widget.onUnknownRoute(settings); final Route<dynamic>? result = widget.onUnknownRoute!(settings);
assert(() { assert(() {
if (result == null) { if (result == null) {
throw FlutterError( throw FlutterError(
......
...@@ -2,8 +2,6 @@ ...@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// @dart = 2.8
import 'dart:ui' as ui show BoxHeightStyle, BoxWidthStyle; import 'dart:ui' as ui show BoxHeightStyle, BoxWidthStyle;
import 'package:flutter/gestures.dart'; import 'package:flutter/gestures.dart';
...@@ -89,7 +87,7 @@ enum OverlayVisibilityMode { ...@@ -89,7 +87,7 @@ enum OverlayVisibilityMode {
class _CupertinoTextFieldSelectionGestureDetectorBuilder extends TextSelectionGestureDetectorBuilder { class _CupertinoTextFieldSelectionGestureDetectorBuilder extends TextSelectionGestureDetectorBuilder {
_CupertinoTextFieldSelectionGestureDetectorBuilder({ _CupertinoTextFieldSelectionGestureDetectorBuilder({
@required _CupertinoTextFieldState state, required _CupertinoTextFieldState state,
}) : _state = state, }) : _state = state,
super(delegate: state); super(delegate: state);
...@@ -102,7 +100,7 @@ class _CupertinoTextFieldSelectionGestureDetectorBuilder extends TextSelectionGe ...@@ -102,7 +100,7 @@ class _CupertinoTextFieldSelectionGestureDetectorBuilder extends TextSelectionGe
// this handler. If the clear button widget recognizes the up event, // this handler. If the clear button widget recognizes the up event,
// then do not handle it. // then do not handle it.
if (_state._clearGlobalKey.currentContext != null) { if (_state._clearGlobalKey.currentContext != null) {
final RenderBox renderBox = _state._clearGlobalKey.currentContext.findRenderObject() as RenderBox; final RenderBox renderBox = _state._clearGlobalKey.currentContext!.findRenderObject() as RenderBox;
final Offset localOffset = renderBox.globalToLocal(details.globalPosition); final Offset localOffset = renderBox.globalToLocal(details.globalPosition);
if (renderBox.hitTest(BoxHitTestResult(), position: localOffset)) { if (renderBox.hitTest(BoxHitTestResult(), position: localOffset)) {
return; return;
...@@ -111,7 +109,7 @@ class _CupertinoTextFieldSelectionGestureDetectorBuilder extends TextSelectionGe ...@@ -111,7 +109,7 @@ class _CupertinoTextFieldSelectionGestureDetectorBuilder extends TextSelectionGe
super.onSingleTapUp(details); super.onSingleTapUp(details);
_state._requestKeyboard(); _state._requestKeyboard();
if (_state.widget.onTap != null) if (_state.widget.onTap != null)
_state.widget.onTap(); _state.widget.onTap!();
} }
@override @override
...@@ -218,7 +216,7 @@ class CupertinoTextField extends StatefulWidget { ...@@ -218,7 +216,7 @@ class CupertinoTextField extends StatefulWidget {
/// * [maxLength], which discusses the precise meaning of "number of /// * [maxLength], which discusses the precise meaning of "number of
/// characters" and how it may differ from the intuitive meaning. /// characters" and how it may differ from the intuitive meaning.
const CupertinoTextField({ const CupertinoTextField({
Key key, Key? key,
this.controller, this.controller,
this.focusNode, this.focusNode,
this.decoration = _kDefaultRoundedBorderDecoration, this.decoration = _kDefaultRoundedBorderDecoration,
...@@ -233,7 +231,7 @@ class CupertinoTextField extends StatefulWidget { ...@@ -233,7 +231,7 @@ class CupertinoTextField extends StatefulWidget {
this.suffix, this.suffix,
this.suffixMode = OverlayVisibilityMode.always, this.suffixMode = OverlayVisibilityMode.always,
this.clearButtonMode = OverlayVisibilityMode.never, this.clearButtonMode = OverlayVisibilityMode.never,
TextInputType keyboardType, TextInputType? keyboardType,
this.textInputAction, this.textInputAction,
this.textCapitalization = TextCapitalization.none, this.textCapitalization = TextCapitalization.none,
this.style, this.style,
...@@ -241,14 +239,14 @@ class CupertinoTextField extends StatefulWidget { ...@@ -241,14 +239,14 @@ class CupertinoTextField extends StatefulWidget {
this.textAlign = TextAlign.start, this.textAlign = TextAlign.start,
this.textAlignVertical, this.textAlignVertical,
this.readOnly = false, this.readOnly = false,
ToolbarOptions toolbarOptions, ToolbarOptions? toolbarOptions,
this.showCursor, this.showCursor,
this.autofocus = false, this.autofocus = false,
this.obscuringCharacter = '•', this.obscuringCharacter = '•',
this.obscureText = false, this.obscureText = false,
this.autocorrect = true, this.autocorrect = true,
SmartDashesType smartDashesType, SmartDashesType? smartDashesType,
SmartQuotesType smartQuotesType, SmartQuotesType? smartQuotesType,
this.enableSuggestions = true, this.enableSuggestions = true,
this.maxLines = 1, this.maxLines = 1,
this.minLines, this.minLines,
...@@ -278,7 +276,8 @@ class CupertinoTextField extends StatefulWidget { ...@@ -278,7 +276,8 @@ class CupertinoTextField extends StatefulWidget {
}) : assert(textAlign != null), }) : assert(textAlign != null),
assert(readOnly != null), assert(readOnly != null),
assert(autofocus != null), assert(autofocus != null),
assert(obscuringCharacter != null && obscuringCharacter.length == 1), // TODO(a14n): uncomment when issue is fixed, https://github.com/dart-lang/sdk/issues/43407
assert(obscuringCharacter != null/* && obscuringCharacter.length == 1*/),
assert(obscureText != null), assert(obscureText != null),
assert(autocorrect != null), assert(autocorrect != null),
smartDashesType = smartDashesType ?? (obscureText ? SmartDashesType.disabled : SmartDashesType.enabled), smartDashesType = smartDashesType ?? (obscureText ? SmartDashesType.disabled : SmartDashesType.enabled),
...@@ -327,16 +326,16 @@ class CupertinoTextField extends StatefulWidget { ...@@ -327,16 +326,16 @@ class CupertinoTextField extends StatefulWidget {
/// Controls the text being edited. /// Controls the text being edited.
/// ///
/// If null, this widget will create its own [TextEditingController]. /// If null, this widget will create its own [TextEditingController].
final TextEditingController controller; final TextEditingController? controller;
/// {@macro flutter.widgets.Focus.focusNode} /// {@macro flutter.widgets.Focus.focusNode}
final FocusNode focusNode; final FocusNode? focusNode;
/// Controls the [BoxDecoration] of the box behind the text input. /// Controls the [BoxDecoration] of the box behind the text input.
/// ///
/// Defaults to having a rounded rectangle grey border and can be null to have /// Defaults to having a rounded rectangle grey border and can be null to have
/// no box decoration. /// no box decoration.
final BoxDecoration decoration; final BoxDecoration? decoration;
/// Padding around the text entry area between the [prefix] and [suffix] /// Padding around the text entry area between the [prefix] and [suffix]
/// or the clear button when [clearButtonMode] is not never. /// or the clear button when [clearButtonMode] is not never.
...@@ -351,7 +350,7 @@ class CupertinoTextField extends StatefulWidget { ...@@ -351,7 +350,7 @@ class CupertinoTextField extends StatefulWidget {
/// ///
/// The text style of the placeholder text matches that of the text field's /// The text style of the placeholder text matches that of the text field's
/// main text entry except a lighter font weight and a grey font color. /// main text entry except a lighter font weight and a grey font color.
final String placeholder; final String? placeholder;
/// The style to use for the placeholder text. /// The style to use for the placeholder text.
/// ///
...@@ -362,10 +361,10 @@ class CupertinoTextField extends StatefulWidget { ...@@ -362,10 +361,10 @@ class CupertinoTextField extends StatefulWidget {
/// Defaults to the [style] property with w300 font weight and grey color. /// Defaults to the [style] property with w300 font weight and grey color.
/// ///
/// If specifically set to null, placeholder's style will be the same as [style]. /// If specifically set to null, placeholder's style will be the same as [style].
final TextStyle placeholderStyle; final TextStyle? placeholderStyle;
/// An optional [Widget] to display before the text. /// An optional [Widget] to display before the text.
final Widget prefix; final Widget? prefix;
/// Controls the visibility of the [prefix] widget based on the state of /// Controls the visibility of the [prefix] widget based on the state of
/// text entry when the [prefix] argument is not null. /// text entry when the [prefix] argument is not null.
...@@ -376,7 +375,7 @@ class CupertinoTextField extends StatefulWidget { ...@@ -376,7 +375,7 @@ class CupertinoTextField extends StatefulWidget {
final OverlayVisibilityMode prefixMode; final OverlayVisibilityMode prefixMode;
/// An optional [Widget] to display after the text. /// An optional [Widget] to display after the text.
final Widget suffix; final Widget? suffix;
/// Controls the visibility of the [suffix] widget based on the state of /// Controls the visibility of the [suffix] widget based on the state of
/// text entry when the [suffix] argument is not null. /// text entry when the [suffix] argument is not null.
...@@ -403,7 +402,7 @@ class CupertinoTextField extends StatefulWidget { ...@@ -403,7 +402,7 @@ class CupertinoTextField extends StatefulWidget {
/// ///
/// Defaults to [TextInputAction.newline] if [keyboardType] is /// Defaults to [TextInputAction.newline] if [keyboardType] is
/// [TextInputType.multiline] and [TextInputAction.done] otherwise. /// [TextInputType.multiline] and [TextInputAction.done] otherwise.
final TextInputAction textInputAction; final TextInputAction? textInputAction;
/// {@macro flutter.widgets.editableText.textCapitalization} /// {@macro flutter.widgets.editableText.textCapitalization}
final TextCapitalization textCapitalization; final TextCapitalization textCapitalization;
...@@ -413,10 +412,10 @@ class CupertinoTextField extends StatefulWidget { ...@@ -413,10 +412,10 @@ class CupertinoTextField extends StatefulWidget {
/// Also serves as a base for the [placeholder] text's style. /// Also serves as a base for the [placeholder] text's style.
/// ///
/// Defaults to the standard iOS font style from [CupertinoTheme] if null. /// Defaults to the standard iOS font style from [CupertinoTheme] if null.
final TextStyle style; final TextStyle? style;
/// {@macro flutter.widgets.editableText.strutStyle} /// {@macro flutter.widgets.editableText.strutStyle}
final StrutStyle strutStyle; final StrutStyle? strutStyle;
/// {@macro flutter.widgets.editableText.textAlign} /// {@macro flutter.widgets.editableText.textAlign}
final TextAlign textAlign; final TextAlign textAlign;
...@@ -429,13 +428,13 @@ class CupertinoTextField extends StatefulWidget { ...@@ -429,13 +428,13 @@ class CupertinoTextField extends StatefulWidget {
final ToolbarOptions toolbarOptions; final ToolbarOptions toolbarOptions;
/// {@macro flutter.widgets.inputDecorator.textAlignVertical} /// {@macro flutter.widgets.inputDecorator.textAlignVertical}
final TextAlignVertical textAlignVertical; final TextAlignVertical? textAlignVertical;
/// {@macro flutter.widgets.editableText.readOnly} /// {@macro flutter.widgets.editableText.readOnly}
final bool readOnly; final bool readOnly;
/// {@macro flutter.widgets.editableText.showCursor} /// {@macro flutter.widgets.editableText.showCursor}
final bool showCursor; final bool? showCursor;
/// {@macro flutter.widgets.editableText.autofocus} /// {@macro flutter.widgets.editableText.autofocus}
final bool autofocus; final bool autofocus;
...@@ -459,10 +458,10 @@ class CupertinoTextField extends StatefulWidget { ...@@ -459,10 +458,10 @@ class CupertinoTextField extends StatefulWidget {
final bool enableSuggestions; final bool enableSuggestions;
/// {@macro flutter.widgets.editableText.maxLines} /// {@macro flutter.widgets.editableText.maxLines}
final int maxLines; final int? maxLines;
/// {@macro flutter.widgets.editableText.minLines} /// {@macro flutter.widgets.editableText.minLines}
final int minLines; final int? minLines;
/// {@macro flutter.widgets.editableText.expands} /// {@macro flutter.widgets.editableText.expands}
final bool expands; final bool expands;
...@@ -509,7 +508,7 @@ class CupertinoTextField extends StatefulWidget { ...@@ -509,7 +508,7 @@ class CupertinoTextField extends StatefulWidget {
/// ///
/// * [LengthLimitingTextInputFormatter] for more information on how it /// * [LengthLimitingTextInputFormatter] for more information on how it
/// counts characters, and how it may differ from the intuitive meaning. /// counts characters, and how it may differ from the intuitive meaning.
final int maxLength; final int? maxLength;
/// If true, prevents the field from allowing more than [maxLength] /// If true, prevents the field from allowing more than [maxLength]
/// characters. /// characters.
...@@ -520,10 +519,10 @@ class CupertinoTextField extends StatefulWidget { ...@@ -520,10 +519,10 @@ class CupertinoTextField extends StatefulWidget {
final bool maxLengthEnforced; final bool maxLengthEnforced;
/// {@macro flutter.widgets.editableText.onChanged} /// {@macro flutter.widgets.editableText.onChanged}
final ValueChanged<String> onChanged; final ValueChanged<String>? onChanged;
/// {@macro flutter.widgets.editableText.onEditingComplete} /// {@macro flutter.widgets.editableText.onEditingComplete}
final VoidCallback onEditingComplete; final VoidCallback? onEditingComplete;
/// {@macro flutter.widgets.editableText.onSubmitted} /// {@macro flutter.widgets.editableText.onSubmitted}
/// ///
...@@ -532,23 +531,23 @@ class CupertinoTextField extends StatefulWidget { ...@@ -532,23 +531,23 @@ class CupertinoTextField extends StatefulWidget {
/// * [EditableText.onSubmitted] for an example of how to handle moving to /// * [EditableText.onSubmitted] for an example of how to handle moving to
/// the next/previous field when using [TextInputAction.next] and /// the next/previous field when using [TextInputAction.next] and
/// [TextInputAction.previous] for [textInputAction]. /// [TextInputAction.previous] for [textInputAction].
final ValueChanged<String> onSubmitted; final ValueChanged<String>? onSubmitted;
/// {@macro flutter.widgets.editableText.inputFormatters} /// {@macro flutter.widgets.editableText.inputFormatters}
final List<TextInputFormatter> inputFormatters; final List<TextInputFormatter>? inputFormatters;
/// Disables the text field when false. /// Disables the text field when false.
/// ///
/// Text fields in disabled states have a light grey background and don't /// Text fields in disabled states have a light grey background and don't
/// respond to touch events including the [prefix], [suffix] and the clear /// respond to touch events including the [prefix], [suffix] and the clear
/// button. /// button.
final bool enabled; final bool? enabled;
/// {@macro flutter.widgets.editableText.cursorWidth} /// {@macro flutter.widgets.editableText.cursorWidth}
final double cursorWidth; final double cursorWidth;
/// {@macro flutter.widgets.editableText.cursorHeight} /// {@macro flutter.widgets.editableText.cursorHeight}
final double cursorHeight; final double? cursorHeight;
/// {@macro flutter.widgets.editableText.cursorRadius} /// {@macro flutter.widgets.editableText.cursorRadius}
final Radius cursorRadius; final Radius cursorRadius;
...@@ -558,7 +557,7 @@ class CupertinoTextField extends StatefulWidget { ...@@ -558,7 +557,7 @@ class CupertinoTextField extends StatefulWidget {
/// Defaults to the [CupertinoThemeData.primaryColor] of the ambient theme, /// Defaults to the [CupertinoThemeData.primaryColor] of the ambient theme,
/// which itself defaults to [CupertinoColors.activeBlue] in the light theme /// which itself defaults to [CupertinoColors.activeBlue] in the light theme
/// and [CupertinoColors.activeOrange] in the dark theme. /// and [CupertinoColors.activeOrange] in the dark theme.
final Color cursorColor; final Color? cursorColor;
/// Controls how tall the selection highlight boxes are computed to be. /// Controls how tall the selection highlight boxes are computed to be.
/// ///
...@@ -575,7 +574,7 @@ class CupertinoTextField extends StatefulWidget { ...@@ -575,7 +574,7 @@ class CupertinoTextField extends StatefulWidget {
/// This setting is only honored on iOS devices. /// This setting is only honored on iOS devices.
/// ///
/// If null, defaults to [Brightness.light]. /// If null, defaults to [Brightness.light].
final Brightness keyboardAppearance; final Brightness? keyboardAppearance;
/// {@macro flutter.widgets.editableText.scrollPadding} /// {@macro flutter.widgets.editableText.scrollPadding}
final EdgeInsets scrollPadding; final EdgeInsets scrollPadding;
...@@ -587,23 +586,23 @@ class CupertinoTextField extends StatefulWidget { ...@@ -587,23 +586,23 @@ class CupertinoTextField extends StatefulWidget {
final DragStartBehavior dragStartBehavior; final DragStartBehavior dragStartBehavior;
/// {@macro flutter.widgets.editableText.scrollController} /// {@macro flutter.widgets.editableText.scrollController}
final ScrollController scrollController; final ScrollController? scrollController;
/// {@macro flutter.widgets.editableText.scrollPhysics} /// {@macro flutter.widgets.editableText.scrollPhysics}
final ScrollPhysics scrollPhysics; final ScrollPhysics? scrollPhysics;
/// {@macro flutter.widgets.editableText.selectionEnabled} /// {@macro flutter.widgets.editableText.selectionEnabled}
bool get selectionEnabled => enableInteractiveSelection; bool get selectionEnabled => enableInteractiveSelection;
/// {@macro flutter.material.textfield.onTap} /// {@macro flutter.material.textfield.onTap}
final GestureTapCallback onTap; final GestureTapCallback? onTap;
/// {@macro flutter.widgets.editableText.autofillHints} /// {@macro flutter.widgets.editableText.autofillHints}
/// {@macro flutter.services.autofill.autofillHints} /// {@macro flutter.services.autofill.autofillHints}
final Iterable<String> autofillHints; final Iterable<String>? autofillHints;
/// {@macro flutter.material.textfield.restorationId} /// {@macro flutter.material.textfield.restorationId}
final String restorationId; final String? restorationId;
@override @override
_CupertinoTextFieldState createState() => _CupertinoTextFieldState(); _CupertinoTextFieldState createState() => _CupertinoTextFieldState();
...@@ -649,15 +648,15 @@ class CupertinoTextField extends StatefulWidget { ...@@ -649,15 +648,15 @@ class CupertinoTextField extends StatefulWidget {
class _CupertinoTextFieldState extends State<CupertinoTextField> with RestorationMixin, AutomaticKeepAliveClientMixin<CupertinoTextField> implements TextSelectionGestureDetectorBuilderDelegate { class _CupertinoTextFieldState extends State<CupertinoTextField> with RestorationMixin, AutomaticKeepAliveClientMixin<CupertinoTextField> implements TextSelectionGestureDetectorBuilderDelegate {
final GlobalKey _clearGlobalKey = GlobalKey(); final GlobalKey _clearGlobalKey = GlobalKey();
RestorableTextEditingController _controller; RestorableTextEditingController? _controller;
TextEditingController get _effectiveController => widget.controller ?? _controller.value; TextEditingController get _effectiveController => widget.controller ?? _controller!.value;
FocusNode _focusNode; FocusNode? _focusNode;
FocusNode get _effectiveFocusNode => widget.focusNode ?? (_focusNode ??= FocusNode()); FocusNode get _effectiveFocusNode => widget.focusNode ?? (_focusNode ??= FocusNode());
bool _showSelectionHandles = false; bool _showSelectionHandles = false;
_CupertinoTextFieldSelectionGestureDetectorBuilder _selectionGestureDetectorBuilder; late _CupertinoTextFieldSelectionGestureDetectorBuilder _selectionGestureDetectorBuilder;
// API for TextSelectionGestureDetectorBuilderDelegate. // API for TextSelectionGestureDetectorBuilderDelegate.
@override @override
...@@ -683,10 +682,10 @@ class _CupertinoTextFieldState extends State<CupertinoTextField> with Restoratio ...@@ -683,10 +682,10 @@ class _CupertinoTextFieldState extends State<CupertinoTextField> with Restoratio
void didUpdateWidget(CupertinoTextField oldWidget) { void didUpdateWidget(CupertinoTextField oldWidget) {
super.didUpdateWidget(oldWidget); super.didUpdateWidget(oldWidget);
if (widget.controller == null && oldWidget.controller != null) { if (widget.controller == null && oldWidget.controller != null) {
_createLocalController(oldWidget.controller.value); _createLocalController(oldWidget.controller!.value);
} else if (widget.controller != null && oldWidget.controller == null) { } else if (widget.controller != null && oldWidget.controller == null) {
unregisterFromRestoration(_controller); unregisterFromRestoration(_controller!);
_controller.dispose(); _controller!.dispose();
_controller = null; _controller = null;
} }
final bool isEnabled = widget.enabled ?? true; final bool isEnabled = widget.enabled ?? true;
...@@ -697,7 +696,7 @@ class _CupertinoTextFieldState extends State<CupertinoTextField> with Restoratio ...@@ -697,7 +696,7 @@ class _CupertinoTextFieldState extends State<CupertinoTextField> with Restoratio
} }
@override @override
void restoreState(RestorationBucket oldBucket, bool initialRestore) { void restoreState(RestorationBucket? oldBucket, bool initialRestore) {
if (_controller != null) { if (_controller != null) {
_registerController(); _registerController();
} }
...@@ -705,11 +704,11 @@ class _CupertinoTextFieldState extends State<CupertinoTextField> with Restoratio ...@@ -705,11 +704,11 @@ class _CupertinoTextFieldState extends State<CupertinoTextField> with Restoratio
void _registerController() { void _registerController() {
assert(_controller != null); assert(_controller != null);
registerForRestoration(_controller, 'controller'); registerForRestoration(_controller!, 'controller');
_controller.value.addListener(updateKeepAlive); _controller!.value.addListener(updateKeepAlive);
} }
void _createLocalController([TextEditingValue value]) { void _createLocalController([TextEditingValue? value]) {
assert(_controller == null); assert(_controller == null);
_controller = value == null _controller = value == null
? RestorableTextEditingController() ? RestorableTextEditingController()
...@@ -720,7 +719,7 @@ class _CupertinoTextFieldState extends State<CupertinoTextField> with Restoratio ...@@ -720,7 +719,7 @@ class _CupertinoTextFieldState extends State<CupertinoTextField> with Restoratio
} }
@override @override
String get restorationId => widget.restorationId; String? get restorationId => widget.restorationId;
@override @override
void dispose() { void dispose() {
...@@ -729,13 +728,13 @@ class _CupertinoTextFieldState extends State<CupertinoTextField> with Restoratio ...@@ -729,13 +728,13 @@ class _CupertinoTextFieldState extends State<CupertinoTextField> with Restoratio
super.dispose(); super.dispose();
} }
EditableTextState get _editableText => editableTextKey.currentState; EditableTextState? get _editableText => editableTextKey.currentState;
void _requestKeyboard() { void _requestKeyboard() {
_editableText?.requestKeyboard(); _editableText?.requestKeyboard();
} }
bool _shouldShowSelectionHandles(SelectionChangedCause cause) { bool _shouldShowSelectionHandles(SelectionChangedCause? cause) {
// When the text field is activated by something that doesn't trigger the // When the text field is activated by something that doesn't trigger the
// selection overlay, we shouldn't show the handles either. // selection overlay, we shouldn't show the handles either.
if (!_selectionGestureDetectorBuilder.shouldShowSelectionToolbar) if (!_selectionGestureDetectorBuilder.shouldShowSelectionToolbar)
...@@ -754,7 +753,7 @@ class _CupertinoTextFieldState extends State<CupertinoTextField> with Restoratio ...@@ -754,7 +753,7 @@ class _CupertinoTextFieldState extends State<CupertinoTextField> with Restoratio
return false; return false;
} }
void _handleSelectionChanged(TextSelection selection, SelectionChangedCause cause) { void _handleSelectionChanged(TextSelection selection, SelectionChangedCause? cause) {
if (cause == SelectionChangedCause.longPress) { if (cause == SelectionChangedCause.longPress) {
_editableText?.bringIntoView(selection.base); _editableText?.bringIntoView(selection.base);
} }
...@@ -767,11 +766,11 @@ class _CupertinoTextFieldState extends State<CupertinoTextField> with Restoratio ...@@ -767,11 +766,11 @@ class _CupertinoTextFieldState extends State<CupertinoTextField> with Restoratio
} }
@override @override
bool get wantKeepAlive => _controller?.value?.text?.isNotEmpty == true; bool get wantKeepAlive => _controller?.value.text.isNotEmpty == true;
bool _shouldShowAttachment({ bool _shouldShowAttachment({
OverlayVisibilityMode attachment, required OverlayVisibilityMode attachment,
bool hasText, required bool hasText,
}) { }) {
switch (attachment) { switch (attachment) {
case OverlayVisibilityMode.never: case OverlayVisibilityMode.never:
...@@ -783,8 +782,6 @@ class _CupertinoTextFieldState extends State<CupertinoTextField> with Restoratio ...@@ -783,8 +782,6 @@ class _CupertinoTextFieldState extends State<CupertinoTextField> with Restoratio
case OverlayVisibilityMode.notEditing: case OverlayVisibilityMode.notEditing:
return !hasText; return !hasText;
} }
assert(false);
return null;
} }
bool _showPrefixWidget(TextEditingValue text) { bool _showPrefixWidget(TextEditingValue text) {
...@@ -821,7 +818,7 @@ class _CupertinoTextFieldState extends State<CupertinoTextField> with Restoratio ...@@ -821,7 +818,7 @@ class _CupertinoTextFieldState extends State<CupertinoTextField> with Restoratio
// like a prefix or suffix, in which case it's aligned to the center. // like a prefix or suffix, in which case it's aligned to the center.
TextAlignVertical get _textAlignVertical { TextAlignVertical get _textAlignVertical {
if (widget.textAlignVertical != null) { if (widget.textAlignVertical != null) {
return widget.textAlignVertical; return widget.textAlignVertical!;
} }
return _hasDecoration ? TextAlignVertical.center : TextAlignVertical.top; return _hasDecoration ? TextAlignVertical.center : TextAlignVertical.top;
} }
...@@ -840,11 +837,11 @@ class _CupertinoTextFieldState extends State<CupertinoTextField> with Restoratio ...@@ -840,11 +837,11 @@ class _CupertinoTextFieldState extends State<CupertinoTextField> with Restoratio
return ValueListenableBuilder<TextEditingValue>( return ValueListenableBuilder<TextEditingValue>(
valueListenable: _effectiveController, valueListenable: _effectiveController,
child: editableText, child: editableText,
builder: (BuildContext context, TextEditingValue text, Widget child) { builder: (BuildContext context, TextEditingValue? text, Widget? child) {
return Row(children: <Widget>[ return Row(children: <Widget>[
// Insert a prefix at the front if the prefix visibility mode matches // Insert a prefix at the front if the prefix visibility mode matches
// the current text state. // the current text state.
if (_showPrefixWidget(text)) widget.prefix, if (_showPrefixWidget(text!)) widget.prefix!,
// In the middle part, stack the placeholder on top of the main EditableText // In the middle part, stack the placeholder on top of the main EditableText
// if needed. // if needed.
Expanded( Expanded(
...@@ -856,7 +853,7 @@ class _CupertinoTextFieldState extends State<CupertinoTextField> with Restoratio ...@@ -856,7 +853,7 @@ class _CupertinoTextFieldState extends State<CupertinoTextField> with Restoratio
child: Padding( child: Padding(
padding: widget.padding, padding: widget.padding,
child: Text( child: Text(
widget.placeholder, widget.placeholder!,
maxLines: widget.maxLines, maxLines: widget.maxLines,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
style: placeholderStyle, style: placeholderStyle,
...@@ -864,13 +861,13 @@ class _CupertinoTextFieldState extends State<CupertinoTextField> with Restoratio ...@@ -864,13 +861,13 @@ class _CupertinoTextFieldState extends State<CupertinoTextField> with Restoratio
), ),
), ),
), ),
child, child!,
], ],
), ),
), ),
// First add the explicit suffix if the suffix visibility mode matches. // First add the explicit suffix if the suffix visibility mode matches.
if (_showSuffixWidget(text)) if (_showSuffixWidget(text))
widget.suffix widget.suffix!
// Otherwise, try to show a clear button if its visibility mode matches. // Otherwise, try to show a clear button if its visibility mode matches.
else if (_showClearButton(text)) else if (_showClearButton(text))
GestureDetector( GestureDetector(
...@@ -881,7 +878,7 @@ class _CupertinoTextFieldState extends State<CupertinoTextField> with Restoratio ...@@ -881,7 +878,7 @@ class _CupertinoTextFieldState extends State<CupertinoTextField> with Restoratio
final bool textChanged = _effectiveController.text.isNotEmpty; final bool textChanged = _effectiveController.text.isNotEmpty;
_effectiveController.clear(); _effectiveController.clear();
if (widget.onChanged != null && textChanged) if (widget.onChanged != null && textChanged)
widget.onChanged(_effectiveController.text); widget.onChanged!(_effectiveController.text);
} : null, } : null,
child: Padding( child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 6.0), padding: const EdgeInsets.symmetric(horizontal: 6.0),
...@@ -904,33 +901,33 @@ class _CupertinoTextFieldState extends State<CupertinoTextField> with Restoratio ...@@ -904,33 +901,33 @@ class _CupertinoTextFieldState extends State<CupertinoTextField> with Restoratio
final TextEditingController controller = _effectiveController; final TextEditingController controller = _effectiveController;
final List<TextInputFormatter> formatters = widget.inputFormatters ?? <TextInputFormatter>[]; final List<TextInputFormatter> formatters = widget.inputFormatters ?? <TextInputFormatter>[];
final bool enabled = widget.enabled ?? true; final bool enabled = widget.enabled ?? true;
final Offset cursorOffset = Offset(_iOSHorizontalCursorOffsetPixels / MediaQuery.of(context).devicePixelRatio, 0); final Offset cursorOffset = Offset(_iOSHorizontalCursorOffsetPixels / MediaQuery.of(context)!.devicePixelRatio, 0);
if (widget.maxLength != null && widget.maxLengthEnforced) { if (widget.maxLength != null && widget.maxLengthEnforced) {
formatters.add(LengthLimitingTextInputFormatter(widget.maxLength)); formatters.add(LengthLimitingTextInputFormatter(widget.maxLength));
} }
final CupertinoThemeData themeData = CupertinoTheme.of(context); final CupertinoThemeData themeData = CupertinoTheme.of(context);
final TextStyle resolvedStyle = widget.style?.copyWith( final TextStyle? resolvedStyle = widget.style?.copyWith(
color: CupertinoDynamicColor.resolve(widget.style?.color, context), color: CupertinoDynamicColor.resolve(widget.style?.color, context),
backgroundColor: CupertinoDynamicColor.resolve(widget.style?.backgroundColor, context), backgroundColor: CupertinoDynamicColor.resolve(widget.style?.backgroundColor, context),
); );
final TextStyle textStyle = themeData.textTheme.textStyle.merge(resolvedStyle); final TextStyle textStyle = themeData.textTheme.textStyle.merge(resolvedStyle);
final TextStyle resolvedPlaceholderStyle = widget.placeholderStyle?.copyWith( final TextStyle? resolvedPlaceholderStyle = widget.placeholderStyle?.copyWith(
color: CupertinoDynamicColor.resolve(widget.placeholderStyle?.color, context), color: CupertinoDynamicColor.resolve(widget.placeholderStyle?.color, context),
backgroundColor: CupertinoDynamicColor.resolve(widget.placeholderStyle?.backgroundColor, context), backgroundColor: CupertinoDynamicColor.resolve(widget.placeholderStyle?.backgroundColor, context),
); );
final TextStyle placeholderStyle = textStyle.merge(resolvedPlaceholderStyle); final TextStyle placeholderStyle = textStyle.merge(resolvedPlaceholderStyle);
final Brightness keyboardAppearance = widget.keyboardAppearance ?? CupertinoTheme.brightnessOf(context); final Brightness keyboardAppearance = widget.keyboardAppearance ?? CupertinoTheme.brightnessOf(context)!;
final Color cursorColor = CupertinoDynamicColor.resolve(widget.cursorColor, context) ?? themeData.primaryColor; final Color cursorColor = CupertinoDynamicColor.resolve(widget.cursorColor, context) ?? themeData.primaryColor;
final Color disabledColor = CupertinoDynamicColor.resolve(_kDisabledBackground, context); final Color? disabledColor = CupertinoDynamicColor.resolve(_kDisabledBackground, context);
final Color decorationColor = CupertinoDynamicColor.resolve(widget.decoration?.color, context); final Color? decorationColor = CupertinoDynamicColor.resolve(widget.decoration?.color, context);
final BoxBorder border = widget.decoration?.border; final BoxBorder? border = widget.decoration?.border;
Border resolvedBorder = border as Border; Border resolvedBorder = border as Border;
if (border is Border) { if (border is Border) {
BorderSide resolveBorderSide(BorderSide side) { BorderSide resolveBorderSide(BorderSide side) {
...@@ -948,7 +945,7 @@ class _CupertinoTextFieldState extends State<CupertinoTextField> with Restoratio ...@@ -948,7 +945,7 @@ class _CupertinoTextFieldState extends State<CupertinoTextField> with Restoratio
); );
} }
final BoxDecoration effectiveDecoration = widget.decoration?.copyWith( final BoxDecoration? effectiveDecoration = widget.decoration?.copyWith(
border: resolvedBorder, border: resolvedBorder,
color: enabled ? decorationColor : (decorationColor ?? disabledColor), color: enabled ? decorationColor : (decorationColor ?? disabledColor),
); );
...@@ -1001,7 +998,7 @@ class _CupertinoTextFieldState extends State<CupertinoTextField> with Restoratio ...@@ -1001,7 +998,7 @@ class _CupertinoTextFieldState extends State<CupertinoTextField> with Restoratio
cursorOffset: cursorOffset, cursorOffset: cursorOffset,
paintCursorAboveText: true, paintCursorAboveText: true,
autocorrectionTextRectColor: selectionColor, autocorrectionTextRectColor: selectionColor,
backgroundCursorColor: CupertinoDynamicColor.resolve(CupertinoColors.inactiveGray, context), backgroundCursorColor: CupertinoDynamicColor.resolve(CupertinoColors.inactiveGray, context)!,
selectionHeightStyle: widget.selectionHeightStyle, selectionHeightStyle: widget.selectionHeightStyle,
selectionWidthStyle: widget.selectionWidthStyle, selectionWidthStyle: widget.selectionWidthStyle,
scrollPadding: widget.scrollPadding, scrollPadding: widget.scrollPadding,
......
...@@ -2,8 +2,6 @@ ...@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// @dart = 2.8
import 'dart:collection'; import 'dart:collection';
import 'dart:math' as math; import 'dart:math' as math;
import 'dart:ui' as ui; import 'dart:ui' as ui;
...@@ -68,24 +66,24 @@ const EdgeInsets _kToolbarButtonPadding = EdgeInsets.symmetric(vertical: 10.0, h ...@@ -68,24 +66,24 @@ const EdgeInsets _kToolbarButtonPadding = EdgeInsets.symmetric(vertical: 10.0, h
// Generates the child that's passed into CupertinoTextSelectionToolbar. // Generates the child that's passed into CupertinoTextSelectionToolbar.
class _CupertinoTextSelectionToolbarWrapper extends StatefulWidget { class _CupertinoTextSelectionToolbarWrapper extends StatefulWidget {
const _CupertinoTextSelectionToolbarWrapper({ const _CupertinoTextSelectionToolbarWrapper({
Key key, Key? key,
this.arrowTipX, required this.arrowTipX,
this.barTopY, required this.barTopY,
this.clipboardStatus, this.clipboardStatus,
this.handleCut, this.handleCut,
this.handleCopy, this.handleCopy,
this.handlePaste, this.handlePaste,
this.handleSelectAll, this.handleSelectAll,
this.isArrowPointingDown, required this.isArrowPointingDown,
}) : super(key: key); }) : super(key: key);
final double arrowTipX; final double arrowTipX;
final double barTopY; final double barTopY;
final ClipboardStatusNotifier clipboardStatus; final ClipboardStatusNotifier? clipboardStatus;
final VoidCallback handleCut; final VoidCallback? handleCut;
final VoidCallback handleCopy; final VoidCallback? handleCopy;
final VoidCallback handlePaste; final VoidCallback? handlePaste;
final VoidCallback handleSelectAll; final VoidCallback? handleSelectAll;
final bool isArrowPointingDown; final bool isArrowPointingDown;
@override @override
...@@ -93,7 +91,7 @@ class _CupertinoTextSelectionToolbarWrapper extends StatefulWidget { ...@@ -93,7 +91,7 @@ class _CupertinoTextSelectionToolbarWrapper extends StatefulWidget {
} }
class _CupertinoTextSelectionToolbarWrapperState extends State<_CupertinoTextSelectionToolbarWrapper> { class _CupertinoTextSelectionToolbarWrapperState extends State<_CupertinoTextSelectionToolbarWrapper> {
ClipboardStatusNotifier _clipboardStatus; late ClipboardStatusNotifier _clipboardStatus;
void _onChangedClipboardStatus() { void _onChangedClipboardStatus() {
setState(() { setState(() {
...@@ -115,16 +113,16 @@ class _CupertinoTextSelectionToolbarWrapperState extends State<_CupertinoTextSel ...@@ -115,16 +113,16 @@ class _CupertinoTextSelectionToolbarWrapperState extends State<_CupertinoTextSel
if (oldWidget.clipboardStatus == null && widget.clipboardStatus != null) { if (oldWidget.clipboardStatus == null && widget.clipboardStatus != null) {
_clipboardStatus.removeListener(_onChangedClipboardStatus); _clipboardStatus.removeListener(_onChangedClipboardStatus);
_clipboardStatus.dispose(); _clipboardStatus.dispose();
_clipboardStatus = widget.clipboardStatus; _clipboardStatus = widget.clipboardStatus!;
} else if (oldWidget.clipboardStatus != null) { } else if (oldWidget.clipboardStatus != null) {
if (widget.clipboardStatus == null) { if (widget.clipboardStatus == null) {
_clipboardStatus = ClipboardStatusNotifier(); _clipboardStatus = ClipboardStatusNotifier();
_clipboardStatus.addListener(_onChangedClipboardStatus); _clipboardStatus.addListener(_onChangedClipboardStatus);
oldWidget.clipboardStatus.removeListener(_onChangedClipboardStatus); oldWidget.clipboardStatus!.removeListener(_onChangedClipboardStatus);
} else if (widget.clipboardStatus != oldWidget.clipboardStatus) { } else if (widget.clipboardStatus != oldWidget.clipboardStatus) {
_clipboardStatus = widget.clipboardStatus; _clipboardStatus = widget.clipboardStatus!;
_clipboardStatus.addListener(_onChangedClipboardStatus); _clipboardStatus.addListener(_onChangedClipboardStatus);
oldWidget.clipboardStatus.removeListener(_onChangedClipboardStatus); oldWidget.clipboardStatus!.removeListener(_onChangedClipboardStatus);
} }
} }
if (widget.handlePaste != null) { if (widget.handlePaste != null) {
...@@ -154,12 +152,12 @@ class _CupertinoTextSelectionToolbarWrapperState extends State<_CupertinoTextSel ...@@ -154,12 +152,12 @@ class _CupertinoTextSelectionToolbarWrapperState extends State<_CupertinoTextSel
} }
final List<Widget> items = <Widget>[]; final List<Widget> items = <Widget>[];
final CupertinoLocalizations localizations = CupertinoLocalizations.of(context); final CupertinoLocalizations? localizations = CupertinoLocalizations.of(context);
final EdgeInsets arrowPadding = widget.isArrowPointingDown final EdgeInsets arrowPadding = widget.isArrowPointingDown
? EdgeInsets.only(bottom: _kToolbarArrowSize.height) ? EdgeInsets.only(bottom: _kToolbarArrowSize.height)
: EdgeInsets.only(top: _kToolbarArrowSize.height); : EdgeInsets.only(top: _kToolbarArrowSize.height);
final Widget onePhysicalPixelVerticalDivider = final Widget onePhysicalPixelVerticalDivider =
SizedBox(width: 1.0 / MediaQuery.of(context).devicePixelRatio); SizedBox(width: 1.0 / MediaQuery.of(context)!.devicePixelRatio);
void addToolbarButton( void addToolbarButton(
String text, String text,
...@@ -185,17 +183,17 @@ class _CupertinoTextSelectionToolbarWrapperState extends State<_CupertinoTextSel ...@@ -185,17 +183,17 @@ class _CupertinoTextSelectionToolbarWrapperState extends State<_CupertinoTextSel
} }
if (widget.handleCut != null) { if (widget.handleCut != null) {
addToolbarButton(localizations.cutButtonLabel, widget.handleCut); addToolbarButton(localizations!.cutButtonLabel, widget.handleCut!);
} }
if (widget.handleCopy != null) { if (widget.handleCopy != null) {
addToolbarButton(localizations.copyButtonLabel, widget.handleCopy); addToolbarButton(localizations!.copyButtonLabel, widget.handleCopy!);
} }
if (widget.handlePaste != null if (widget.handlePaste != null
&& _clipboardStatus.value == ClipboardStatus.pasteable) { && _clipboardStatus.value == ClipboardStatus.pasteable) {
addToolbarButton(localizations.pasteButtonLabel, widget.handlePaste); addToolbarButton(localizations!.pasteButtonLabel, widget.handlePaste!);
} }
if (widget.handleSelectAll != null) { if (widget.handleSelectAll != null) {
addToolbarButton(localizations.selectAllButtonLabel, widget.handleSelectAll); addToolbarButton(localizations!.selectAllButtonLabel, widget.handleSelectAll!);
} }
return CupertinoTextSelectionToolbar._( return CupertinoTextSelectionToolbar._(
...@@ -221,11 +219,11 @@ class _CupertinoTextSelectionToolbarWrapperState extends State<_CupertinoTextSel ...@@ -221,11 +219,11 @@ class _CupertinoTextSelectionToolbarWrapperState extends State<_CupertinoTextSel
@visibleForTesting @visibleForTesting
class CupertinoTextSelectionToolbar extends SingleChildRenderObjectWidget { class CupertinoTextSelectionToolbar extends SingleChildRenderObjectWidget {
const CupertinoTextSelectionToolbar._({ const CupertinoTextSelectionToolbar._({
Key key, Key? key,
double barTopY, required double barTopY,
double arrowTipX, required double arrowTipX,
bool isArrowPointingDown, required bool isArrowPointingDown,
Widget child, Widget? child,
}) : _barTopY = barTopY, }) : _barTopY = barTopY,
_arrowTipX = arrowTipX, _arrowTipX = arrowTipX,
_isArrowPointingDown = isArrowPointingDown, _isArrowPointingDown = isArrowPointingDown,
...@@ -257,7 +255,7 @@ class _ToolbarParentData extends BoxParentData { ...@@ -257,7 +255,7 @@ class _ToolbarParentData extends BoxParentData {
// The x offset from the tip of the arrow to the center of the toolbar. // The x offset from the tip of the arrow to the center of the toolbar.
// Positive if the tip of the arrow has a larger x-coordinate than the // Positive if the tip of the arrow has a larger x-coordinate than the
// center of the toolbar. // center of the toolbar.
double arrowXOffsetFromCenter; double? arrowXOffsetFromCenter;
@override @override
String toString() => 'offset=$offset, arrowXOffsetFromCenter=$arrowXOffsetFromCenter'; String toString() => 'offset=$offset, arrowXOffsetFromCenter=$arrowXOffsetFromCenter';
} }
...@@ -267,7 +265,7 @@ class _ToolbarRenderBox extends RenderShiftedBox { ...@@ -267,7 +265,7 @@ class _ToolbarRenderBox extends RenderShiftedBox {
this._barTopY, this._barTopY,
this._arrowTipX, this._arrowTipX,
this._isArrowPointingDown, this._isArrowPointingDown,
RenderBox child, RenderBox? child,
) : super(child); ) : super(child);
...@@ -325,37 +323,37 @@ class _ToolbarRenderBox extends RenderShiftedBox { ...@@ -325,37 +323,37 @@ class _ToolbarRenderBox extends RenderShiftedBox {
.deflate(const EdgeInsets.symmetric(horizontal: _kToolbarScreenPadding)) .deflate(const EdgeInsets.symmetric(horizontal: _kToolbarScreenPadding))
.loosen(); .loosen();
child.layout(heightConstraint.enforce(enforcedConstraint), parentUsesSize: true,); child!.layout(heightConstraint.enforce(enforcedConstraint), parentUsesSize: true,);
final _ToolbarParentData childParentData = child.parentData as _ToolbarParentData; final _ToolbarParentData childParentData = child!.parentData as _ToolbarParentData;
// The local x-coordinate of the center of the toolbar. // The local x-coordinate of the center of the toolbar.
final double lowerBound = child.size.width/2 + _kToolbarScreenPadding; final double lowerBound = child!.size.width/2 + _kToolbarScreenPadding;
final double upperBound = size.width - child.size.width/2 - _kToolbarScreenPadding; final double upperBound = size.width - child!.size.width/2 - _kToolbarScreenPadding;
final double adjustedCenterX = _arrowTipX.clamp(lowerBound, upperBound) as double; final double adjustedCenterX = _arrowTipX.clamp(lowerBound, upperBound);
childParentData.offset = Offset(adjustedCenterX - child.size.width / 2, _barTopY); childParentData.offset = Offset(adjustedCenterX - child!.size.width / 2, _barTopY);
childParentData.arrowXOffsetFromCenter = _arrowTipX - adjustedCenterX; childParentData.arrowXOffsetFromCenter = _arrowTipX - adjustedCenterX;
} }
// The path is described in the toolbar's coordinate system. // The path is described in the toolbar's coordinate system.
Path _clipPath() { Path _clipPath() {
final _ToolbarParentData childParentData = child.parentData as _ToolbarParentData; final _ToolbarParentData childParentData = child!.parentData as _ToolbarParentData;
final Path rrect = Path() final Path rrect = Path()
..addRRect( ..addRRect(
RRect.fromRectAndRadius( RRect.fromRectAndRadius(
Offset(0, _isArrowPointingDown ? 0 : _kToolbarArrowSize.height,) Offset(0, _isArrowPointingDown ? 0 : _kToolbarArrowSize.height)
& Size(child.size.width, child.size.height - _kToolbarArrowSize.height), & Size(child!.size.width, child!.size.height - _kToolbarArrowSize.height),
_kToolbarBorderRadius, _kToolbarBorderRadius,
), ),
); );
final double arrowTipX = child.size.width / 2 + childParentData.arrowXOffsetFromCenter; final double arrowTipX = child!.size.width / 2 + childParentData.arrowXOffsetFromCenter!;
final double arrowBottomY = _isArrowPointingDown final double arrowBottomY = _isArrowPointingDown
? child.size.height - _kToolbarArrowSize.height ? child!.size.height - _kToolbarArrowSize.height
: _kToolbarArrowSize.height; : _kToolbarArrowSize.height;
final double arrowTipY = _isArrowPointingDown ? child.size.height : 0; final double arrowTipY = _isArrowPointingDown ? child!.size.height : 0;
final Path arrow = Path() final Path arrow = Path()
..moveTo(arrowTipX, arrowTipY) ..moveTo(arrowTipX, arrowTipY)
...@@ -372,17 +370,17 @@ class _ToolbarRenderBox extends RenderShiftedBox { ...@@ -372,17 +370,17 @@ class _ToolbarRenderBox extends RenderShiftedBox {
return; return;
} }
final _ToolbarParentData childParentData = child.parentData as _ToolbarParentData; final _ToolbarParentData childParentData = child!.parentData as _ToolbarParentData;
context.pushClipPath( context.pushClipPath(
needsCompositing, needsCompositing,
offset + childParentData.offset, offset + childParentData.offset,
Offset.zero & child.size, Offset.zero & child!.size,
_clipPath(), _clipPath(),
(PaintingContext innerContext, Offset innerOffset) => innerContext.paintChild(child, innerOffset), (PaintingContext innerContext, Offset innerOffset) => innerContext.paintChild(child!, innerOffset),
); );
} }
Paint _debugPaint; Paint? _debugPaint;
@override @override
void debugPaintSize(PaintingContext context, Offset offset) { void debugPaintSize(PaintingContext context, Offset offset) {
...@@ -395,15 +393,15 @@ class _ToolbarRenderBox extends RenderShiftedBox { ...@@ -395,15 +393,15 @@ class _ToolbarRenderBox extends RenderShiftedBox {
..shader = ui.Gradient.linear( ..shader = ui.Gradient.linear(
const Offset(0.0, 0.0), const Offset(0.0, 0.0),
const Offset(10.0, 10.0), const Offset(10.0, 10.0),
<Color>[const Color(0x00000000), const Color(0xFFFF00FF), const Color(0xFFFF00FF), const Color(0x00000000)], const <Color>[Color(0x00000000), Color(0xFFFF00FF), Color(0xFFFF00FF), Color(0x00000000)],
<double>[0.25, 0.25, 0.75, 0.75], const <double>[0.25, 0.25, 0.75, 0.75],
TileMode.repeated, TileMode.repeated,
) )
..strokeWidth = 2.0 ..strokeWidth = 2.0
..style = PaintingStyle.stroke; ..style = PaintingStyle.stroke;
final _ToolbarParentData childParentData = child.parentData as _ToolbarParentData; final _ToolbarParentData childParentData = child!.parentData as _ToolbarParentData;
context.canvas.drawPath(_clipPath().shift(offset + childParentData.offset), _debugPaint); context.canvas.drawPath(_clipPath().shift(offset + childParentData.offset), _debugPaint!);
return true; return true;
}()); }());
} }
...@@ -463,7 +461,7 @@ class _CupertinoTextSelectionControls extends TextSelectionControls { ...@@ -463,7 +461,7 @@ class _CupertinoTextSelectionControls extends TextSelectionControls {
ClipboardStatusNotifier clipboardStatus, ClipboardStatusNotifier clipboardStatus,
) { ) {
assert(debugCheckHasMediaQuery(context)); assert(debugCheckHasMediaQuery(context));
final MediaQueryData mediaQuery = MediaQuery.of(context); final MediaQueryData mediaQuery = MediaQuery.of(context)!;
// The toolbar should appear below the TextField when there is not enough // The toolbar should appear below the TextField when there is not enough
// space above the TextField to show it, assuming there's always enough space // space above the TextField to show it, assuming there's always enough space
...@@ -478,7 +476,7 @@ class _CupertinoTextSelectionControls extends TextSelectionControls { ...@@ -478,7 +476,7 @@ class _CupertinoTextSelectionControls extends TextSelectionControls {
final double arrowTipX = (position.dx + globalEditableRegion.left).clamp( final double arrowTipX = (position.dx + globalEditableRegion.left).clamp(
_kArrowScreenPadding + mediaQuery.padding.left, _kArrowScreenPadding + mediaQuery.padding.left,
mediaQuery.size.width - mediaQuery.padding.right - _kArrowScreenPadding, mediaQuery.size.width - mediaQuery.padding.right - _kArrowScreenPadding,
) as double; );
// The y-coordinate has to be calculated instead of directly quoting position.dy, // The y-coordinate has to be calculated instead of directly quoting position.dy,
// since the caller (TextSelectionOverlay._buildToolbar) does not know whether // since the caller (TextSelectionOverlay._buildToolbar) does not know whether
...@@ -532,8 +530,6 @@ class _CupertinoTextSelectionControls extends TextSelectionControls { ...@@ -532,8 +530,6 @@ class _CupertinoTextSelectionControls extends TextSelectionControls {
case TextSelectionHandleType.collapsed: case TextSelectionHandleType.collapsed:
return const SizedBox(); return const SizedBox();
} }
assert(type != null);
return null;
} }
/// Gets anchor for cupertino-style text selection handles. /// Gets anchor for cupertino-style text selection handles.
...@@ -570,9 +566,9 @@ class _CupertinoTextSelectionControls extends TextSelectionControls { ...@@ -570,9 +566,9 @@ class _CupertinoTextSelectionControls extends TextSelectionControls {
// Renders the content of the selection menu and maintains the page state. // Renders the content of the selection menu and maintains the page state.
class _CupertinoTextSelectionToolbarContent extends StatefulWidget { class _CupertinoTextSelectionToolbarContent extends StatefulWidget {
const _CupertinoTextSelectionToolbarContent({ const _CupertinoTextSelectionToolbarContent({
Key key, Key? key,
@required this.children, required this.children,
@required this.isArrowPointingDown, required this.isArrowPointingDown,
}) : assert(children != null), }) : assert(children != null),
// This ignore is used because .isNotEmpty isn't compatible with const. // This ignore is used because .isNotEmpty isn't compatible with const.
assert(children.length > 0), // ignore: prefer_is_empty assert(children.length > 0), // ignore: prefer_is_empty
...@@ -587,9 +583,9 @@ class _CupertinoTextSelectionToolbarContent extends StatefulWidget { ...@@ -587,9 +583,9 @@ class _CupertinoTextSelectionToolbarContent extends StatefulWidget {
class _CupertinoTextSelectionToolbarContentState extends State<_CupertinoTextSelectionToolbarContent> with TickerProviderStateMixin { class _CupertinoTextSelectionToolbarContentState extends State<_CupertinoTextSelectionToolbarContent> with TickerProviderStateMixin {
// Controls the fading of the buttons within the menu during page transitions. // Controls the fading of the buttons within the menu during page transitions.
AnimationController _controller; late AnimationController _controller;
int _page = 0; int _page = 0;
int _nextPage; int? _nextPage;
void _handleNextPage() { void _handleNextPage() {
_controller.reverse(); _controller.reverse();
...@@ -609,7 +605,7 @@ class _CupertinoTextSelectionToolbarContentState extends State<_CupertinoTextSel ...@@ -609,7 +605,7 @@ class _CupertinoTextSelectionToolbarContentState extends State<_CupertinoTextSel
} }
setState(() { setState(() {
_page = _nextPage; _page = _nextPage!;
_nextPage = null; _nextPage = null;
}); });
_controller.forward(); _controller.forward();
...@@ -666,7 +662,7 @@ class _CupertinoTextSelectionToolbarContentState extends State<_CupertinoTextSel ...@@ -666,7 +662,7 @@ class _CupertinoTextSelectionToolbarContentState extends State<_CupertinoTextSel
pressedOpacity: 0.7, pressedOpacity: 0.7,
child: const Text('◀', style: _kToolbarButtonFontStyle), child: const Text('◀', style: _kToolbarButtonFontStyle),
), ),
dividerWidth: 1.0 / MediaQuery.of(context).devicePixelRatio, dividerWidth: 1.0 / MediaQuery.of(context)!.devicePixelRatio,
nextButton: CupertinoButton( nextButton: CupertinoButton(
borderRadius: null, borderRadius: null,
color: _kToolbarBackgroundColor, color: _kToolbarBackgroundColor,
...@@ -698,13 +694,13 @@ class _CupertinoTextSelectionToolbarContentState extends State<_CupertinoTextSel ...@@ -698,13 +694,13 @@ class _CupertinoTextSelectionToolbarContentState extends State<_CupertinoTextSel
// _CupertinoTextSelectionToolbarItemsElement, paginates the menu items. // _CupertinoTextSelectionToolbarItemsElement, paginates the menu items.
class _CupertinoTextSelectionToolbarItems extends RenderObjectWidget { class _CupertinoTextSelectionToolbarItems extends RenderObjectWidget {
_CupertinoTextSelectionToolbarItems({ _CupertinoTextSelectionToolbarItems({
Key key, Key? key,
@required this.page, required this.page,
@required this.children, required this.children,
@required this.backButton, required this.backButton,
@required this.dividerWidth, required this.dividerWidth,
@required this.nextButton, required this.nextButton,
@required this.nextButtonDisabled, required this.nextButtonDisabled,
}) : assert(children != null), }) : assert(children != null),
assert(children.isNotEmpty), assert(children.isNotEmpty),
assert(backButton != null), assert(backButton != null),
...@@ -746,7 +742,7 @@ class _CupertinoTextSelectionToolbarItemsElement extends RenderObjectElement { ...@@ -746,7 +742,7 @@ class _CupertinoTextSelectionToolbarItemsElement extends RenderObjectElement {
_CupertinoTextSelectionToolbarItems widget, _CupertinoTextSelectionToolbarItems widget,
) : super(widget); ) : super(widget);
List<Element> _children; late List<Element> _children;
final Map<_CupertinoTextSelectionToolbarItemsSlot, Element> slotToChild = <_CupertinoTextSelectionToolbarItemsSlot, Element>{}; final Map<_CupertinoTextSelectionToolbarItemsSlot, Element> slotToChild = <_CupertinoTextSelectionToolbarItemsSlot, Element>{};
// We keep a set of forgotten children to avoid O(n^2) work walking _children // We keep a set of forgotten children to avoid O(n^2) work walking _children
...@@ -759,7 +755,7 @@ class _CupertinoTextSelectionToolbarItemsElement extends RenderObjectElement { ...@@ -759,7 +755,7 @@ class _CupertinoTextSelectionToolbarItemsElement extends RenderObjectElement {
@override @override
_CupertinoTextSelectionToolbarItemsRenderBox get renderObject => super.renderObject as _CupertinoTextSelectionToolbarItemsRenderBox; _CupertinoTextSelectionToolbarItemsRenderBox get renderObject => super.renderObject as _CupertinoTextSelectionToolbarItemsRenderBox;
void _updateRenderObject(RenderBox child, _CupertinoTextSelectionToolbarItemsSlot slot) { void _updateRenderObject(RenderBox? child, _CupertinoTextSelectionToolbarItemsSlot slot) {
switch (slot) { switch (slot) {
case _CupertinoTextSelectionToolbarItemsSlot.backButton: case _CupertinoTextSelectionToolbarItemsSlot.backButton:
renderObject.backButton = child; renderObject.backButton = child;
...@@ -783,7 +779,7 @@ class _CupertinoTextSelectionToolbarItemsElement extends RenderObjectElement { ...@@ -783,7 +779,7 @@ class _CupertinoTextSelectionToolbarItemsElement extends RenderObjectElement {
} }
if (slot is IndexedSlot) { if (slot is IndexedSlot) {
assert(renderObject.debugValidateChild(child)); assert(renderObject.debugValidateChild(child));
renderObject.insert(child as RenderBox, after: slot?.value?.renderObject as RenderBox); renderObject.insert(child as RenderBox, after: slot.value?.renderObject as RenderBox);
return; return;
} }
assert(false, 'slot must be _CupertinoTextSelectionToolbarItemsSlot or IndexedSlot'); assert(false, 'slot must be _CupertinoTextSelectionToolbarItemsSlot or IndexedSlot');
...@@ -793,11 +789,11 @@ class _CupertinoTextSelectionToolbarItemsElement extends RenderObjectElement { ...@@ -793,11 +789,11 @@ class _CupertinoTextSelectionToolbarItemsElement extends RenderObjectElement {
@override @override
void moveRenderObjectChild(RenderObject child, IndexedSlot<Element> oldSlot, IndexedSlot<Element> newSlot) { void moveRenderObjectChild(RenderObject child, IndexedSlot<Element> oldSlot, IndexedSlot<Element> newSlot) {
assert(child.parent == renderObject); assert(child.parent == renderObject);
renderObject.move(child as RenderBox, after: newSlot?.value?.renderObject as RenderBox); renderObject.move(child as RenderBox, after: newSlot.value.renderObject as RenderBox);
} }
static bool _shouldPaint(Element child) { static bool _shouldPaint(Element child) {
return (child.renderObject.parentData as ToolbarItemsParentData).shouldPaint; return (child.renderObject!.parentData as ToolbarItemsParentData).shouldPaint;
} }
@override @override
...@@ -842,8 +838,8 @@ class _CupertinoTextSelectionToolbarItemsElement extends RenderObjectElement { ...@@ -842,8 +838,8 @@ class _CupertinoTextSelectionToolbarItemsElement extends RenderObjectElement {
// Mount or update slotted child. // Mount or update slotted child.
void _mountChild(Widget widget, _CupertinoTextSelectionToolbarItemsSlot slot) { void _mountChild(Widget widget, _CupertinoTextSelectionToolbarItemsSlot slot) {
final Element oldChild = slotToChild[slot]; final Element? oldChild = slotToChild[slot];
final Element newChild = updateChild(oldChild, widget, slot); final Element? newChild = updateChild(oldChild, widget, slot);
if (oldChild != null) { if (oldChild != null) {
slotToChild.remove(slot); slotToChild.remove(slot);
} }
...@@ -853,7 +849,7 @@ class _CupertinoTextSelectionToolbarItemsElement extends RenderObjectElement { ...@@ -853,7 +849,7 @@ class _CupertinoTextSelectionToolbarItemsElement extends RenderObjectElement {
} }
@override @override
void mount(Element parent, dynamic newSlot) { void mount(Element? parent, dynamic newSlot) {
super.mount(parent, newSlot); super.mount(parent, newSlot);
// Mount slotted children. // Mount slotted children.
_mountChild(widget.backButton, _CupertinoTextSelectionToolbarItemsSlot.backButton); _mountChild(widget.backButton, _CupertinoTextSelectionToolbarItemsSlot.backButton);
...@@ -861,10 +857,10 @@ class _CupertinoTextSelectionToolbarItemsElement extends RenderObjectElement { ...@@ -861,10 +857,10 @@ class _CupertinoTextSelectionToolbarItemsElement extends RenderObjectElement {
_mountChild(widget.nextButtonDisabled, _CupertinoTextSelectionToolbarItemsSlot.nextButtonDisabled); _mountChild(widget.nextButtonDisabled, _CupertinoTextSelectionToolbarItemsSlot.nextButtonDisabled);
// Mount list children. // Mount list children.
_children = List<Element>(widget.children.length); _children = List<Element>.filled(widget.children.length, _NullElement.instance);
Element previousChild; Element? previousChild;
for (int i = 0; i < _children.length; i += 1) { for (int i = 0; i < _children.length; i += 1) {
final Element newChild = inflateWidget(widget.children[i], IndexedSlot<Element>(i, previousChild)); final Element newChild = inflateWidget(widget.children[i], IndexedSlot<Element?>(i, previousChild));
_children[i] = newChild; _children[i] = newChild;
previousChild = newChild; previousChild = newChild;
} }
...@@ -903,8 +899,8 @@ class _CupertinoTextSelectionToolbarItemsElement extends RenderObjectElement { ...@@ -903,8 +899,8 @@ class _CupertinoTextSelectionToolbarItemsElement extends RenderObjectElement {
// The custom RenderBox that helps paginate the menu items. // The custom RenderBox that helps paginate the menu items.
class _CupertinoTextSelectionToolbarItemsRenderBox extends RenderBox with ContainerRenderObjectMixin<RenderBox, ToolbarItemsParentData>, RenderBoxContainerDefaultsMixin<RenderBox, ToolbarItemsParentData> { class _CupertinoTextSelectionToolbarItemsRenderBox extends RenderBox with ContainerRenderObjectMixin<RenderBox, ToolbarItemsParentData>, RenderBoxContainerDefaultsMixin<RenderBox, ToolbarItemsParentData> {
_CupertinoTextSelectionToolbarItemsRenderBox({ _CupertinoTextSelectionToolbarItemsRenderBox({
@required double dividerWidth, required double dividerWidth,
@required int page, required int page,
}) : assert(dividerWidth != null), }) : assert(dividerWidth != null),
assert(page != null), assert(page != null),
_dividerWidth = dividerWidth, _dividerWidth = dividerWidth,
...@@ -913,7 +909,7 @@ class _CupertinoTextSelectionToolbarItemsRenderBox extends RenderBox with Contai ...@@ -913,7 +909,7 @@ class _CupertinoTextSelectionToolbarItemsRenderBox extends RenderBox with Contai
final Map<_CupertinoTextSelectionToolbarItemsSlot, RenderBox> slottedChildren = <_CupertinoTextSelectionToolbarItemsSlot, RenderBox>{}; final Map<_CupertinoTextSelectionToolbarItemsSlot, RenderBox> slottedChildren = <_CupertinoTextSelectionToolbarItemsSlot, RenderBox>{};
RenderBox _updateChild(RenderBox oldChild, RenderBox newChild, _CupertinoTextSelectionToolbarItemsSlot slot) { RenderBox? _updateChild(RenderBox? oldChild, RenderBox? newChild, _CupertinoTextSelectionToolbarItemsSlot slot) {
if (oldChild != null) { if (oldChild != null) {
dropChild(oldChild); dropChild(oldChild);
slottedChildren.remove(slot); slottedChildren.remove(slot);
...@@ -949,21 +945,21 @@ class _CupertinoTextSelectionToolbarItemsRenderBox extends RenderBox with Contai ...@@ -949,21 +945,21 @@ class _CupertinoTextSelectionToolbarItemsRenderBox extends RenderBox with Contai
markNeedsLayout(); markNeedsLayout();
} }
RenderBox _backButton; RenderBox? _backButton;
RenderBox get backButton => _backButton; RenderBox? get backButton => _backButton;
set backButton(RenderBox value) { set backButton(RenderBox? value) {
_backButton = _updateChild(_backButton, value, _CupertinoTextSelectionToolbarItemsSlot.backButton); _backButton = _updateChild(_backButton, value, _CupertinoTextSelectionToolbarItemsSlot.backButton);
} }
RenderBox _nextButton; RenderBox? _nextButton;
RenderBox get nextButton => _nextButton; RenderBox? get nextButton => _nextButton;
set nextButton(RenderBox value) { set nextButton(RenderBox? value) {
_nextButton = _updateChild(_nextButton, value, _CupertinoTextSelectionToolbarItemsSlot.nextButton); _nextButton = _updateChild(_nextButton, value, _CupertinoTextSelectionToolbarItemsSlot.nextButton);
} }
RenderBox _nextButtonDisabled; RenderBox? _nextButtonDisabled;
RenderBox get nextButtonDisabled => _nextButtonDisabled; RenderBox? get nextButtonDisabled => _nextButtonDisabled;
set nextButtonDisabled(RenderBox value) { set nextButtonDisabled(RenderBox? value) {
_nextButtonDisabled = _updateChild(_nextButtonDisabled, value, _CupertinoTextSelectionToolbarItemsSlot.nextButtonDisabled); _nextButtonDisabled = _updateChild(_nextButtonDisabled, value, _CupertinoTextSelectionToolbarItemsSlot.nextButtonDisabled);
} }
...@@ -975,15 +971,15 @@ class _CupertinoTextSelectionToolbarItemsRenderBox extends RenderBox with Contai ...@@ -975,15 +971,15 @@ class _CupertinoTextSelectionToolbarItemsRenderBox extends RenderBox with Contai
} }
// Layout slotted children. // Layout slotted children.
_backButton.layout(constraints.loosen(), parentUsesSize: true); _backButton!.layout(constraints.loosen(), parentUsesSize: true);
_nextButton.layout(constraints.loosen(), parentUsesSize: true); _nextButton!.layout(constraints.loosen(), parentUsesSize: true);
_nextButtonDisabled.layout(constraints.loosen(), parentUsesSize: true); _nextButtonDisabled!.layout(constraints.loosen(), parentUsesSize: true);
final double subsequentPageButtonsWidth = final double subsequentPageButtonsWidth =
_backButton.size.width + _nextButton.size.width; _backButton!.size.width + _nextButton!.size.width;
double currentButtonPosition = 0.0; double currentButtonPosition = 0.0;
double toolbarWidth; // The width of the whole widget. late double toolbarWidth; // The width of the whole widget.
double firstPageWidth; late double firstPageWidth;
int currentPage = 0; int currentPage = 0;
int i = -1; int i = -1;
visitChildren((RenderObject renderObjectChild) { visitChildren((RenderObject renderObjectChild) {
...@@ -1002,7 +998,7 @@ class _CupertinoTextSelectionToolbarItemsRenderBox extends RenderBox with Contai ...@@ -1002,7 +998,7 @@ class _CupertinoTextSelectionToolbarItemsRenderBox extends RenderBox with Contai
if (currentPage == 0) { if (currentPage == 0) {
// If this is the last child, it's ok to fit without a forward button. // If this is the last child, it's ok to fit without a forward button.
paginationButtonsWidth = paginationButtonsWidth =
i == childCount - 1 ? 0.0 : _nextButton.size.width; i == childCount - 1 ? 0.0 : _nextButton!.size.width;
} else { } else {
paginationButtonsWidth = subsequentPageButtonsWidth; paginationButtonsWidth = subsequentPageButtonsWidth;
} }
...@@ -1022,8 +1018,8 @@ class _CupertinoTextSelectionToolbarItemsRenderBox extends RenderBox with Contai ...@@ -1022,8 +1018,8 @@ class _CupertinoTextSelectionToolbarItemsRenderBox extends RenderBox with Contai
currentButtonPosition + paginationButtonsWidth + child.size.width; currentButtonPosition + paginationButtonsWidth + child.size.width;
if (currentWidth > constraints.maxWidth) { if (currentWidth > constraints.maxWidth) {
currentPage++; currentPage++;
currentButtonPosition = _backButton.size.width + dividerWidth; currentButtonPosition = _backButton!.size.width + dividerWidth;
paginationButtonsWidth = _backButton.size.width + _nextButton.size.width; paginationButtonsWidth = _backButton!.size.width + _nextButton!.size.width;
child.layout( child.layout(
BoxConstraints.loose(Size( BoxConstraints.loose(Size(
firstPageWidth - paginationButtonsWidth, firstPageWidth - paginationButtonsWidth,
...@@ -1037,7 +1033,7 @@ class _CupertinoTextSelectionToolbarItemsRenderBox extends RenderBox with Contai ...@@ -1037,7 +1033,7 @@ class _CupertinoTextSelectionToolbarItemsRenderBox extends RenderBox with Contai
childParentData.shouldPaint = currentPage == page; childParentData.shouldPaint = currentPage == page;
if (currentPage == 0) { if (currentPage == 0) {
firstPageWidth = currentButtonPosition + _nextButton.size.width; firstPageWidth = currentButtonPosition + _nextButton!.size.width;
} }
if (currentPage == page) { if (currentPage == page) {
toolbarWidth = currentButtonPosition; toolbarWidth = currentButtonPosition;
...@@ -1050,21 +1046,21 @@ class _CupertinoTextSelectionToolbarItemsRenderBox extends RenderBox with Contai ...@@ -1050,21 +1046,21 @@ class _CupertinoTextSelectionToolbarItemsRenderBox extends RenderBox with Contai
// Position page nav buttons. // Position page nav buttons.
if (currentPage > 0) { if (currentPage > 0) {
final ToolbarItemsParentData nextButtonParentData = final ToolbarItemsParentData nextButtonParentData =
_nextButton.parentData as ToolbarItemsParentData; _nextButton!.parentData as ToolbarItemsParentData;
final ToolbarItemsParentData nextButtonDisabledParentData = final ToolbarItemsParentData nextButtonDisabledParentData =
_nextButtonDisabled.parentData as ToolbarItemsParentData; _nextButtonDisabled!.parentData as ToolbarItemsParentData;
final ToolbarItemsParentData backButtonParentData = final ToolbarItemsParentData backButtonParentData =
_backButton.parentData as ToolbarItemsParentData; _backButton!.parentData as ToolbarItemsParentData;
// The forward button always shows if there is more than one page, even on // The forward button always shows if there is more than one page, even on
// the last page (it's just disabled). // the last page (it's just disabled).
if (page == currentPage) { if (page == currentPage) {
nextButtonDisabledParentData.offset = Offset(toolbarWidth, 0.0); nextButtonDisabledParentData.offset = Offset(toolbarWidth, 0.0);
nextButtonDisabledParentData.shouldPaint = true; nextButtonDisabledParentData.shouldPaint = true;
toolbarWidth += nextButtonDisabled.size.width; toolbarWidth += nextButtonDisabled!.size.width;
} else { } else {
nextButtonParentData.offset = Offset(toolbarWidth, 0.0); nextButtonParentData.offset = Offset(toolbarWidth, 0.0);
nextButtonParentData.shouldPaint = true; nextButtonParentData.shouldPaint = true;
toolbarWidth += nextButton.size.width; toolbarWidth += nextButton!.size.width;
} }
if (page > 0) { if (page > 0) {
backButtonParentData.offset = Offset.zero; backButtonParentData.offset = Offset.zero;
...@@ -1102,7 +1098,7 @@ class _CupertinoTextSelectionToolbarItemsRenderBox extends RenderBox with Contai ...@@ -1102,7 +1098,7 @@ class _CupertinoTextSelectionToolbarItemsRenderBox extends RenderBox with Contai
} }
// Returns true iff the single child is hit by the given position. // Returns true iff the single child is hit by the given position.
static bool hitTestChild(RenderBox child, BoxHitTestResult result, { Offset position }) { static bool hitTestChild(RenderBox? child, BoxHitTestResult result, { required Offset position }) {
if (child == null) { if (child == null) {
return false; return false;
} }
...@@ -1119,10 +1115,10 @@ class _CupertinoTextSelectionToolbarItemsRenderBox extends RenderBox with Contai ...@@ -1119,10 +1115,10 @@ class _CupertinoTextSelectionToolbarItemsRenderBox extends RenderBox with Contai
} }
@override @override
bool hitTestChildren(BoxHitTestResult result, { Offset position }) { bool hitTestChildren(BoxHitTestResult result, { required Offset position }) {
// Hit test list children. // Hit test list children.
// The x, y parameters have the top left of the node's box as the origin. // The x, y parameters have the top left of the node's box as the origin.
RenderBox child = lastChild; RenderBox? child = lastChild;
while (child != null) { while (child != null) {
final ToolbarItemsParentData childParentData = child.parentData as ToolbarItemsParentData; final ToolbarItemsParentData childParentData = child.parentData as ToolbarItemsParentData;
...@@ -1186,13 +1182,13 @@ class _CupertinoTextSelectionToolbarItemsRenderBox extends RenderBox with Contai ...@@ -1186,13 +1182,13 @@ class _CupertinoTextSelectionToolbarItemsRenderBox extends RenderBox with Contai
void visitChildren(RenderObjectVisitor visitor) { void visitChildren(RenderObjectVisitor visitor) {
// Visit the slotted children. // Visit the slotted children.
if (_backButton != null) { if (_backButton != null) {
visitor(_backButton); visitor(_backButton!);
} }
if (_nextButton != null) { if (_nextButton != null) {
visitor(_nextButton); visitor(_nextButton!);
} }
if (_nextButtonDisabled != null) { if (_nextButtonDisabled != null) {
visitor(_nextButtonDisabled); visitor(_nextButtonDisabled!);
} }
// Visit the list children. // Visit the list children.
super.visitChildren(visitor); super.visitChildren(visitor);
...@@ -1214,9 +1210,6 @@ class _CupertinoTextSelectionToolbarItemsRenderBox extends RenderBox with Contai ...@@ -1214,9 +1210,6 @@ class _CupertinoTextSelectionToolbarItemsRenderBox extends RenderBox with Contai
List<DiagnosticsNode> debugDescribeChildren() { List<DiagnosticsNode> debugDescribeChildren() {
final List<DiagnosticsNode> value = <DiagnosticsNode>[]; final List<DiagnosticsNode> value = <DiagnosticsNode>[];
visitChildren((RenderObject renderObjectChild) { visitChildren((RenderObject renderObjectChild) {
if (renderObjectChild == null) {
return;
}
final RenderBox child = renderObjectChild as RenderBox; final RenderBox child = renderObjectChild as RenderBox;
if (child == backButton) { if (child == backButton) {
value.add(child.toDiagnosticsNode(name: 'back button')); value.add(child.toDiagnosticsNode(name: 'back button'));
...@@ -1244,3 +1237,20 @@ enum _CupertinoTextSelectionToolbarItemsSlot { ...@@ -1244,3 +1237,20 @@ enum _CupertinoTextSelectionToolbarItemsSlot {
/// Text selection controls that follows iOS design conventions. /// Text selection controls that follows iOS design conventions.
final TextSelectionControls cupertinoTextSelectionControls = _CupertinoTextSelectionControls(); final TextSelectionControls cupertinoTextSelectionControls = _CupertinoTextSelectionControls();
class _NullElement extends Element {
_NullElement() : super(_NullWidget());
static _NullElement instance = _NullElement();
@override
bool get debugDoingBuild => throw UnimplementedError();
@override
void performRebuild() { }
}
class _NullWidget extends Widget {
@override
Element createElement() => throw UnimplementedError();
}
\ No newline at end of file
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