migrate some cupertino files to nullsafety (#66424)

* migrate some cupertino files to nullsafety

* address review comments
This commit is contained in:
Alexandre Ardhuin 2020-09-23 23:12:42 +02:00 committed by GitHub
parent 707aa49e42
commit 29fae79c72
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 727 additions and 744 deletions

View file

@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:ui' show ImageFilter;
import 'package:flutter/foundation.dart';
@ -113,7 +111,7 @@ class CupertinoActionSheet extends StatelessWidget {
/// Generally, action sheets are used to give the user a choice between
/// two or more choices for the current context.
const CupertinoActionSheet({
Key key,
Key? key,
this.title,
this.message,
this.actions,
@ -129,37 +127,37 @@ class CupertinoActionSheet extends StatelessWidget {
/// the font of the [title] is bold.
///
/// Typically a [Text] widget.
final Widget title;
final Widget? title;
/// An optional descriptive message that provides more details about the
/// reason for the alert.
///
/// Typically a [Text] widget.
final Widget message;
final Widget? message;
/// The set of actions that are displayed for the user to select.
///
/// Typically this is a list of [CupertinoActionSheetAction] widgets.
final List<Widget> actions;
final List<Widget>? actions;
/// A scroll controller that can be used to control the scrolling of the
/// [message] in the action sheet.
///
/// This attribute is typically not needed, as alert messages should be
/// short.
final ScrollController messageScrollController;
final ScrollController? messageScrollController;
/// A scroll controller that can be used to control the scrolling of the
/// [actions] in the action sheet.
///
/// This attribute is typically not needed.
final ScrollController actionScrollController;
final ScrollController? actionScrollController;
/// The optional cancel button that is grouped separately from the other
/// actions.
///
/// Typically this is an [CupertinoActionSheetAction] widget.
final Widget cancelButton;
final Widget? cancelButton;
Widget _buildContent(BuildContext context) {
final List<Widget> content = <Widget>[];
@ -183,14 +181,14 @@ class CupertinoActionSheet extends StatelessWidget {
}
Widget _buildActions() {
if (actions == null || actions.isEmpty) {
if (actions == null || actions!.isEmpty) {
return Container(
height: 0.0,
);
}
return Container(
child: _CupertinoAlertActionSection(
children: actions,
children: actions!,
scrollController: actionScrollController,
hasCancelButton: cancelButton != null,
),
@ -210,6 +208,8 @@ class CupertinoActionSheet extends StatelessWidget {
@override
Widget build(BuildContext context) {
assert(debugCheckHasMediaQuery(context));
final List<Widget> children = <Widget>[
Flexible(child: ClipRRect(
borderRadius: BorderRadius.circular(12.0),
@ -225,12 +225,12 @@ class CupertinoActionSheet extends StatelessWidget {
if (cancelButton != null) _buildCancelButton(),
];
final Orientation orientation = MediaQuery.of(context).orientation;
final Orientation orientation = MediaQuery.of(context)!.orientation;
double actionSheetWidth;
if (orientation == Orientation.portrait) {
actionSheetWidth = MediaQuery.of(context).size.width - (_kEdgeHorizontalPadding * 2);
actionSheetWidth = MediaQuery.of(context)!.size.width - (_kEdgeHorizontalPadding * 2);
} else {
actionSheetWidth = MediaQuery.of(context).size.height - (_kEdgeHorizontalPadding * 2);
actionSheetWidth = MediaQuery.of(context)!.size.height - (_kEdgeHorizontalPadding * 2);
}
return SafeArea(
@ -270,11 +270,11 @@ class CupertinoActionSheetAction extends StatelessWidget {
///
/// The [child] and [onPressed] arguments must not be null.
const CupertinoActionSheetAction({
Key key,
@required this.onPressed,
Key? key,
required this.onPressed,
this.isDefaultAction = false,
this.isDestructiveAction = false,
@required this.child,
required this.child,
}) : assert(child != null),
assert(onPressed != null),
super(key: key);
@ -340,11 +340,11 @@ class CupertinoActionSheetAction extends StatelessWidget {
class _CupertinoActionSheetCancelButton extends StatefulWidget {
const _CupertinoActionSheetCancelButton({
Key key,
Key? key,
this.child,
}) : super(key: key);
final Widget child;
final Widget? child;
@override
_CupertinoActionSheetCancelButtonState createState() => _CupertinoActionSheetCancelButtonState();
@ -388,9 +388,9 @@ class _CupertinoActionSheetCancelButtonState extends State<_CupertinoActionSheet
class _CupertinoAlertRenderWidget extends RenderObjectWidget {
const _CupertinoAlertRenderWidget({
Key key,
@required this.contentSection,
@required this.actionsSection,
Key? key,
required this.contentSection,
required this.actionsSection,
}) : super(key: key);
final Widget contentSection;
@ -398,16 +398,17 @@ class _CupertinoAlertRenderWidget extends RenderObjectWidget {
@override
RenderObject createRenderObject(BuildContext context) {
assert(debugCheckHasMediaQuery(context));
return _RenderCupertinoAlert(
dividerThickness: _kDividerThickness / MediaQuery.of(context).devicePixelRatio,
dividerColor: CupertinoDynamicColor.resolve(_kButtonDividerColor, context),
dividerThickness: _kDividerThickness / MediaQuery.of(context)!.devicePixelRatio,
dividerColor: CupertinoDynamicColor.resolve(_kButtonDividerColor, context)!,
);
}
@override
void updateRenderObject(BuildContext context, _RenderCupertinoAlert renderObject) {
super.updateRenderObject(context, renderObject);
renderObject.dividerColor = CupertinoDynamicColor.resolve(_kButtonDividerColor, context);
renderObject.dividerColor = CupertinoDynamicColor.resolve(_kButtonDividerColor, context)!;
}
@override
@ -419,27 +420,27 @@ class _CupertinoAlertRenderWidget extends RenderObjectWidget {
class _CupertinoAlertRenderElement extends RenderObjectElement {
_CupertinoAlertRenderElement(_CupertinoAlertRenderWidget widget) : super(widget);
Element _contentElement;
Element _actionsElement;
Element? _contentElement;
Element? _actionsElement;
@override
_CupertinoAlertRenderWidget get widget => super.widget as _CupertinoAlertRenderWidget;
@override
_RenderCupertinoAlert get renderObject => super.renderObject as _RenderCupertinoAlert;
_RenderCupertinoAlert? get renderObject => super.renderObject as _RenderCupertinoAlert?;
@override
void visitChildren(ElementVisitor visitor) {
if (_contentElement != null) {
visitor(_contentElement);
visitor(_contentElement!);
}
if (_actionsElement != null) {
visitor(_actionsElement);
visitor(_actionsElement!);
}
}
@override
void mount(Element parent, dynamic newSlot) {
void mount(Element? parent, dynamic newSlot) {
super.mount(parent, newSlot);
_contentElement = updateChild(_contentElement,
widget.contentSection, _AlertSections.contentSection);
@ -479,11 +480,11 @@ class _CupertinoAlertRenderElement extends RenderObjectElement {
@override
void removeRenderObjectChild(RenderObject child, _AlertSections slot) {
assert(child == renderObject.contentSection || child == renderObject.actionsSection);
if (renderObject.contentSection == child) {
renderObject.contentSection = null;
} else if (renderObject.actionsSection == child) {
renderObject.actionsSection = null;
assert(child == renderObject!.contentSection || child == renderObject!.actionsSection);
if (renderObject!.contentSection == child) {
renderObject!.contentSection = null;
} else if (renderObject!.actionsSection == child) {
renderObject!.actionsSection = null;
}
}
@ -491,10 +492,10 @@ class _CupertinoAlertRenderElement extends RenderObjectElement {
assert(slot != null);
switch (slot) {
case _AlertSections.contentSection:
renderObject.contentSection = child as RenderBox;
renderObject!.contentSection = child as RenderBox;
break;
case _AlertSections.actionsSection:
renderObject.actionsSection = child as RenderBox;
renderObject!.actionsSection = child as RenderBox;
break;
}
}
@ -520,10 +521,10 @@ class _CupertinoAlertRenderElement extends RenderObjectElement {
// to take up any remaining space that was not consumed by the content section.
class _RenderCupertinoAlert extends RenderBox {
_RenderCupertinoAlert({
RenderBox contentSection,
RenderBox actionsSection,
RenderBox? contentSection,
RenderBox? actionsSection,
double dividerThickness = 0.0,
@required Color dividerColor,
required Color dividerColor,
}) : assert(dividerColor != null),
_contentSection = contentSection,
_actionsSection = actionsSection,
@ -532,30 +533,30 @@ class _RenderCupertinoAlert extends RenderBox {
..color = dividerColor
..style = PaintingStyle.fill;
RenderBox get contentSection => _contentSection;
RenderBox _contentSection;
set contentSection(RenderBox newContentSection) {
RenderBox? get contentSection => _contentSection;
RenderBox? _contentSection;
set contentSection(RenderBox? newContentSection) {
if (newContentSection != _contentSection) {
if (null != _contentSection) {
dropChild(_contentSection);
dropChild(_contentSection!);
}
_contentSection = newContentSection;
if (null != _contentSection) {
adoptChild(_contentSection);
adoptChild(_contentSection!);
}
}
}
RenderBox get actionsSection => _actionsSection;
RenderBox _actionsSection;
set actionsSection(RenderBox newActionsSection) {
RenderBox? get actionsSection => _actionsSection;
RenderBox? _actionsSection;
set actionsSection(RenderBox? newActionsSection) {
if (newActionsSection != _actionsSection) {
if (null != _actionsSection) {
dropChild(_actionsSection);
dropChild(_actionsSection!);
}
_actionsSection = newActionsSection;
if (null != _actionsSection) {
adoptChild(_actionsSection);
adoptChild(_actionsSection!);
}
}
}
@ -576,10 +577,10 @@ class _RenderCupertinoAlert extends RenderBox {
void attach(PipelineOwner owner) {
super.attach(owner);
if (null != contentSection) {
contentSection.attach(owner);
contentSection!.attach(owner);
}
if (null != actionsSection) {
actionsSection.attach(owner);
actionsSection!.attach(owner);
}
}
@ -587,20 +588,20 @@ class _RenderCupertinoAlert extends RenderBox {
void detach() {
super.detach();
if (null != contentSection) {
contentSection.detach();
contentSection!.detach();
}
if (null != actionsSection) {
actionsSection.detach();
actionsSection!.detach();
}
}
@override
void redepthChildren() {
if (null != contentSection) {
redepthChild(contentSection);
redepthChild(contentSection!);
}
if (null != actionsSection) {
redepthChild(actionsSection);
redepthChild(actionsSection!);
}
}
@ -614,10 +615,10 @@ class _RenderCupertinoAlert extends RenderBox {
@override
void visitChildren(RenderObjectVisitor visitor) {
if (contentSection != null) {
visitor(contentSection);
visitor(contentSection!);
}
if (actionsSection != null) {
visitor(actionsSection);
visitor(actionsSection!);
}
}
@ -625,10 +626,10 @@ class _RenderCupertinoAlert extends RenderBox {
List<DiagnosticsNode> debugDescribeChildren() {
final List<DiagnosticsNode> value = <DiagnosticsNode>[];
if (contentSection != null) {
value.add(contentSection.toDiagnosticsNode(name: 'content'));
value.add(contentSection!.toDiagnosticsNode(name: 'content'));
}
if (actionsSection != null) {
value.add(actionsSection.toDiagnosticsNode(name: 'actions'));
value.add(actionsSection!.toDiagnosticsNode(name: 'actions'));
}
return value;
}
@ -645,8 +646,8 @@ class _RenderCupertinoAlert extends RenderBox {
@override
double computeMinIntrinsicHeight(double width) {
final double contentHeight = contentSection.getMinIntrinsicHeight(width);
final double actionsHeight = actionsSection.getMinIntrinsicHeight(width);
final double contentHeight = contentSection!.getMinIntrinsicHeight(width);
final double actionsHeight = actionsSection!.getMinIntrinsicHeight(width);
final bool hasDivider = contentHeight > 0.0 && actionsHeight > 0.0;
double height = contentHeight + (hasDivider ? _dividerThickness : 0.0) + actionsHeight;
@ -659,8 +660,8 @@ class _RenderCupertinoAlert extends RenderBox {
@override
double computeMaxIntrinsicHeight(double width) {
final double contentHeight = contentSection.getMaxIntrinsicHeight(width);
final double actionsHeight = actionsSection.getMaxIntrinsicHeight(width);
final double contentHeight = contentSection!.getMaxIntrinsicHeight(width);
final double actionsHeight = actionsSection!.getMaxIntrinsicHeight(width);
final bool hasDivider = contentHeight > 0.0 && actionsHeight > 0.0;
double height = contentHeight + (hasDivider ? _dividerThickness : 0.0) + actionsHeight;
@ -674,25 +675,25 @@ class _RenderCupertinoAlert extends RenderBox {
@override
void performLayout() {
final BoxConstraints constraints = this.constraints;
final bool hasDivider = contentSection.getMaxIntrinsicHeight(constraints.maxWidth) > 0.0
&& actionsSection.getMaxIntrinsicHeight(constraints.maxWidth) > 0.0;
final bool hasDivider = contentSection!.getMaxIntrinsicHeight(constraints.maxWidth) > 0.0
&& actionsSection!.getMaxIntrinsicHeight(constraints.maxWidth) > 0.0;
final double dividerThickness = hasDivider ? _dividerThickness : 0.0;
final double minActionsHeight = actionsSection.getMinIntrinsicHeight(constraints.maxWidth);
final double minActionsHeight = actionsSection!.getMinIntrinsicHeight(constraints.maxWidth);
// Size alert content.
contentSection.layout(
contentSection!.layout(
constraints.deflate(EdgeInsets.only(bottom: minActionsHeight + dividerThickness)),
parentUsesSize: true,
);
final Size contentSize = contentSection.size;
final Size contentSize = contentSection!.size;
// Size alert actions.
actionsSection.layout(
actionsSection!.layout(
constraints.deflate(EdgeInsets.only(top: contentSize.height + dividerThickness)),
parentUsesSize: true,
);
final Size actionsSize = actionsSection.size;
final Size actionsSize = actionsSection!.size;
// Calculate overall alert height.
final double actionSheetHeight = contentSize.height + dividerThickness + actionsSize.height;
@ -702,30 +703,30 @@ class _RenderCupertinoAlert extends RenderBox {
// Set the position of the actions box to sit at the bottom of the alert.
// The content box defaults to the top left, which is where we want it.
assert(actionsSection.parentData is MultiChildLayoutParentData);
final MultiChildLayoutParentData actionParentData = actionsSection.parentData as MultiChildLayoutParentData;
assert(actionsSection!.parentData is MultiChildLayoutParentData);
final MultiChildLayoutParentData actionParentData = actionsSection!.parentData as MultiChildLayoutParentData;
actionParentData.offset = Offset(0.0, contentSize.height + dividerThickness);
}
@override
void paint(PaintingContext context, Offset offset) {
final MultiChildLayoutParentData contentParentData = contentSection.parentData as MultiChildLayoutParentData;
contentSection.paint(context, offset + contentParentData.offset);
final MultiChildLayoutParentData contentParentData = contentSection!.parentData as MultiChildLayoutParentData;
contentSection!.paint(context, offset + contentParentData.offset);
final bool hasDivider = contentSection.size.height > 0.0 && actionsSection.size.height > 0.0;
final bool hasDivider = contentSection!.size.height > 0.0 && actionsSection!.size.height > 0.0;
if (hasDivider) {
_paintDividerBetweenContentAndActions(context.canvas, offset);
}
final MultiChildLayoutParentData actionsParentData = actionsSection.parentData as MultiChildLayoutParentData;
actionsSection.paint(context, offset + actionsParentData.offset);
final MultiChildLayoutParentData actionsParentData = actionsSection!.parentData as MultiChildLayoutParentData;
actionsSection!.paint(context, offset + actionsParentData.offset);
}
void _paintDividerBetweenContentAndActions(Canvas canvas, Offset offset) {
canvas.drawRect(
Rect.fromLTWH(
offset.dx,
offset.dy + contentSection.size.height,
offset.dy + contentSection!.size.height,
size.width,
_dividerThickness,
),
@ -734,15 +735,15 @@ class _RenderCupertinoAlert extends RenderBox {
}
@override
bool hitTestChildren(BoxHitTestResult result, { Offset position }) {
final MultiChildLayoutParentData contentSectionParentData = contentSection.parentData as MultiChildLayoutParentData;
final MultiChildLayoutParentData actionsSectionParentData = actionsSection.parentData as MultiChildLayoutParentData;
bool hitTestChildren(BoxHitTestResult result, { required Offset position }) {
final MultiChildLayoutParentData contentSectionParentData = contentSection!.parentData as MultiChildLayoutParentData;
final MultiChildLayoutParentData actionsSectionParentData = actionsSection!.parentData as MultiChildLayoutParentData;
return result.addWithPaintOffset(
offset: contentSectionParentData.offset,
position: position,
hitTest: (BoxHitTestResult result, Offset transformed) {
assert(transformed == position - contentSectionParentData.offset);
return contentSection.hitTest(result, position: transformed);
return contentSection!.hitTest(result, position: transformed);
},
)
|| result.addWithPaintOffset(
@ -750,7 +751,7 @@ class _RenderCupertinoAlert extends RenderBox {
position: position,
hitTest: (BoxHitTestResult result, Offset transformed) {
assert(transformed == position - actionsSectionParentData.offset);
return actionsSection.hitTest(result, position: transformed);
return actionsSection!.hitTest(result, position: transformed);
},
);
}
@ -770,7 +771,7 @@ enum _AlertSections {
// a SingleChildScrollView with a zero-sized Container.
class _CupertinoAlertContentSection extends StatelessWidget {
const _CupertinoAlertContentSection({
Key key,
Key? key,
this.title,
this.message,
this.scrollController,
@ -780,20 +781,20 @@ class _CupertinoAlertContentSection extends StatelessWidget {
// the font of the title is bold.
//
// Typically a Text widget.
final Widget title;
final Widget? title;
// An optional descriptive message that provides more details about the
// reason for the alert.
//
// Typically a Text widget.
final Widget message;
final Widget? message;
// A scroll controller that can be used to control the scrolling of the
// content in the action sheet.
//
// Defaults to null, and is typically not needed, since most alert contents
// are short.
final ScrollController scrollController;
final ScrollController? scrollController;
@override
Widget build(BuildContext context) {
@ -811,7 +812,7 @@ class _CupertinoAlertContentSection extends StatelessWidget {
style: message == null ? _kActionSheetContentStyle
: _kActionSheetContentStyle.copyWith(fontWeight: FontWeight.w600),
textAlign: TextAlign.center,
child: title,
child: title!,
),
));
}
@ -829,7 +830,7 @@ class _CupertinoAlertContentSection extends StatelessWidget {
style: title == null ? _kActionSheetContentStyle.copyWith(fontWeight: FontWeight.w600)
: _kActionSheetContentStyle,
textAlign: TextAlign.center,
child: message,
child: message!,
),
),
);
@ -869,8 +870,8 @@ class _CupertinoAlertContentSection extends StatelessWidget {
// and layout.
class _CupertinoAlertActionSection extends StatefulWidget {
const _CupertinoAlertActionSection({
Key key,
@required this.children,
Key? key,
required this.children,
this.scrollController,
this.hasCancelButton,
}) : assert(children != null),
@ -883,9 +884,9 @@ class _CupertinoAlertActionSection extends StatefulWidget {
//
// Defaults to null, and is typically not needed, since most alerts
// don't have many actions.
final ScrollController scrollController;
final ScrollController? scrollController;
final bool hasCancelButton;
final bool? hasCancelButton;
@override
_CupertinoAlertActionSectionState createState() => _CupertinoAlertActionSectionState();
@ -894,7 +895,7 @@ class _CupertinoAlertActionSection extends StatefulWidget {
class _CupertinoAlertActionSectionState extends State<_CupertinoAlertActionSection> {
@override
Widget build(BuildContext context) {
final double devicePixelRatio = MediaQuery.of(context).devicePixelRatio;
final double devicePixelRatio = MediaQuery.of(context)!.devicePixelRatio;
final List<Widget> interactiveButtons = <Widget>[];
for (int i = 0; i < widget.children.length; i += 1) {
@ -911,7 +912,7 @@ class _CupertinoAlertActionSectionState extends State<_CupertinoAlertActionSecti
child: _CupertinoAlertActionsRenderWidget(
actionButtons: interactiveButtons,
dividerThickness: _kDividerThickness / devicePixelRatio,
hasCancelButton: widget.hasCancelButton,
hasCancelButton: widget.hasCancelButton ?? false,
),
),
);
@ -925,7 +926,7 @@ class _CupertinoAlertActionSectionState extends State<_CupertinoAlertActionSecti
// appropriately by _RenderCupertinoAlertActions.
class _PressableActionButton extends StatefulWidget {
const _PressableActionButton({
@required this.child,
required this.child,
});
final Widget child;
@ -966,9 +967,9 @@ class _PressableActionButtonState extends State<_PressableActionButton> {
// incoming isPressed property.
class _ActionButtonParentDataWidget extends ParentDataWidget<_ActionButtonParentData> {
const _ActionButtonParentDataWidget({
Key key,
this.isPressed,
@required Widget child,
Key? key,
required this.isPressed,
required Widget child,
}) : super(key: key, child: child);
final bool isPressed;
@ -981,7 +982,7 @@ class _ActionButtonParentDataWidget extends ParentDataWidget<_ActionButtonParent
parentData.isPressed = isPressed;
// Force a repaint.
final AbstractNode targetParent = renderObject.parent;
final AbstractNode? targetParent = renderObject.parent;
if (targetParent is RenderObject)
targetParent.markNeedsPaint();
}
@ -1006,8 +1007,8 @@ class _ActionButtonParentData extends MultiChildLayoutParentData {
// See _RenderCupertinoAlertActions for specific layout policy details.
class _CupertinoAlertActionsRenderWidget extends MultiChildRenderObjectWidget {
_CupertinoAlertActionsRenderWidget({
Key key,
@required List<Widget> actionButtons,
Key? key,
required List<Widget> actionButtons,
double dividerThickness = 0.0,
bool hasCancelButton = false,
}) : _dividerThickness = dividerThickness,
@ -1021,10 +1022,10 @@ class _CupertinoAlertActionsRenderWidget extends MultiChildRenderObjectWidget {
RenderObject createRenderObject(BuildContext context) {
return _RenderCupertinoAlertActions(
dividerThickness: _dividerThickness,
dividerColor: CupertinoDynamicColor.resolve(_kButtonDividerColor, context),
dividerColor: CupertinoDynamicColor.resolve(_kButtonDividerColor, context)!,
hasCancelButton: _hasCancelButton,
backgroundColor: CupertinoDynamicColor.resolve(_kBackgroundColor, context),
pressedColor: CupertinoDynamicColor.resolve(_kPressedColor, context),
backgroundColor: CupertinoDynamicColor.resolve(_kBackgroundColor, context)!,
pressedColor: CupertinoDynamicColor.resolve(_kPressedColor, context)!,
);
}
@ -1032,10 +1033,10 @@ class _CupertinoAlertActionsRenderWidget extends MultiChildRenderObjectWidget {
void updateRenderObject(BuildContext context, _RenderCupertinoAlertActions renderObject) {
renderObject
..dividerThickness = _dividerThickness
..dividerColor = CupertinoDynamicColor.resolve(_kButtonDividerColor, context)
..dividerColor = CupertinoDynamicColor.resolve(_kButtonDividerColor, context)!
..hasCancelButton = _hasCancelButton
..backgroundColor = CupertinoDynamicColor.resolve(_kBackgroundColor, context)
..pressedColor = CupertinoDynamicColor.resolve(_kPressedColor, context);
..backgroundColor = CupertinoDynamicColor.resolve(_kBackgroundColor, context)!
..pressedColor = CupertinoDynamicColor.resolve(_kPressedColor, context)!;
}
}
@ -1061,12 +1062,12 @@ class _RenderCupertinoAlertActions extends RenderBox
with ContainerRenderObjectMixin<RenderBox, MultiChildLayoutParentData>,
RenderBoxContainerDefaultsMixin<RenderBox, MultiChildLayoutParentData> {
_RenderCupertinoAlertActions({
List<RenderBox> children,
List<RenderBox>? children,
double dividerThickness = 0.0,
@required Color dividerColor,
required Color dividerColor,
bool hasCancelButton = false,
Color backgroundColor,
Color pressedColor,
required Color backgroundColor,
required Color pressedColor,
}) : _dividerThickness = dividerThickness,
_hasCancelButton = hasCancelButton,
_buttonBackgroundPaint = Paint()
@ -1159,7 +1160,7 @@ class _RenderCupertinoAlertActions extends RenderBox
if (childCount == 0)
return 0.0;
if (childCount == 1)
return firstChild.computeMaxIntrinsicHeight(width) + dividerThickness;
return firstChild!.computeMaxIntrinsicHeight(width) + dividerThickness;
if (hasCancelButton && childCount < 4)
return _computeMinIntrinsicHeightWithCancel(width);
return _computeMinIntrinsicHeightWithoutCancel(width);
@ -1170,13 +1171,13 @@ class _RenderCupertinoAlertActions extends RenderBox
double _computeMinIntrinsicHeightWithCancel(double width) {
assert(childCount == 2 || childCount == 3);
if (childCount == 2) {
return firstChild.getMinIntrinsicHeight(width)
+ childAfter(firstChild).getMinIntrinsicHeight(width)
return firstChild!.getMinIntrinsicHeight(width)
+ childAfter(firstChild!)!.getMinIntrinsicHeight(width)
+ dividerThickness;
}
return firstChild.getMinIntrinsicHeight(width)
+ childAfter(firstChild).getMinIntrinsicHeight(width)
+ childAfter(childAfter(firstChild)).getMinIntrinsicHeight(width)
return firstChild!.getMinIntrinsicHeight(width)
+ childAfter(firstChild!)!.getMinIntrinsicHeight(width)
+ childAfter(childAfter(firstChild!)!)!.getMinIntrinsicHeight(width)
+ (dividerThickness * 2);
}
@ -1185,9 +1186,9 @@ class _RenderCupertinoAlertActions extends RenderBox
// + 50% the height of the 2nd button + 2 dividers.
double _computeMinIntrinsicHeightWithoutCancel(double width) {
assert(childCount >= 2);
return firstChild.getMinIntrinsicHeight(width)
return firstChild!.getMinIntrinsicHeight(width)
+ dividerThickness
+ (0.5 * childAfter(firstChild).getMinIntrinsicHeight(width));
+ (0.5 * childAfter(firstChild!)!.getMinIntrinsicHeight(width));
}
@override
@ -1195,7 +1196,7 @@ class _RenderCupertinoAlertActions extends RenderBox
if (childCount == 0)
return 0.0;
if (childCount == 1)
return firstChild.computeMaxIntrinsicHeight(width) + dividerThickness;
return firstChild!.computeMaxIntrinsicHeight(width) + dividerThickness;
return _computeMaxIntrinsicHeightStacked(width);
}
@ -1206,7 +1207,7 @@ class _RenderCupertinoAlertActions extends RenderBox
final double allDividersHeight = (childCount - 1) * dividerThickness;
double heightAccumulation = allDividersHeight;
RenderBox button = firstChild;
RenderBox? button = firstChild;
while (button != null) {
heightAccumulation += button.getMaxIntrinsicHeight(width);
button = childAfter(button);
@ -1221,7 +1222,7 @@ class _RenderCupertinoAlertActions extends RenderBox
maxHeight: double.infinity,
);
RenderBox child = firstChild;
RenderBox? child = firstChild;
int index = 0;
double verticalOffset = 0.0;
while (child != null) {
@ -1269,8 +1270,8 @@ class _RenderCupertinoAlertActions extends RenderBox
Offset accumulatingOffset = offset;
RenderBox child = firstChild;
RenderBox prevChild;
RenderBox? child = firstChild;
RenderBox? prevChild;
while (child != null) {
assert(child.parentData is _ActionButtonParentData);
final _ActionButtonParentData currentButtonParentData = child.parentData as _ActionButtonParentData;
@ -1327,7 +1328,7 @@ class _RenderCupertinoAlertActions extends RenderBox
}
void _drawButtons(PaintingContext context, Offset offset) {
RenderBox child = firstChild;
RenderBox? child = firstChild;
while (child != null) {
final MultiChildLayoutParentData childParentData = child.parentData as MultiChildLayoutParentData;
context.paintChild(child, childParentData.offset + offset);
@ -1336,7 +1337,7 @@ class _RenderCupertinoAlertActions extends RenderBox
}
@override
bool hitTestChildren(BoxHitTestResult result, { Offset position }) {
bool hitTestChildren(BoxHitTestResult result, { required Offset position }) {
return defaultHitTestChildren(result, position: position);
}
}

View file

@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';
@ -70,16 +68,16 @@ class CupertinoApp extends StatefulWidget {
///
/// The boolean arguments, [routes], and [navigatorObservers], must not be null.
const CupertinoApp({
Key key,
Key? key,
this.navigatorKey,
this.home,
this.theme,
this.routes = const <String, WidgetBuilder>{},
Map<String, Widget Function(BuildContext)> this.routes = const <String, WidgetBuilder>{},
this.initialRoute,
this.onGenerateRoute,
this.onGenerateInitialRoutes,
this.onUnknownRoute,
this.navigatorObservers = const <NavigatorObserver>[],
List<NavigatorObserver> this.navigatorObservers = const <NavigatorObserver>[],
this.builder,
this.title = '',
this.onGenerateTitle,
@ -112,10 +110,10 @@ class CupertinoApp extends StatefulWidget {
/// Creates a [CupertinoApp] that uses the [Router] instead of a [Navigator].
const CupertinoApp.router({
Key key,
Key? key,
this.routeInformationProvider,
@required this.routeInformationParser,
@required this.routerDelegate,
required RouteInformationParser<Object> this.routeInformationParser,
required RouterDelegate<Object> this.routerDelegate,
this.backButtonDispatcher,
this.theme,
this.builder,
@ -151,16 +149,16 @@ class CupertinoApp extends StatefulWidget {
super(key: key);
/// {@macro flutter.widgets.widgetsApp.navigatorKey}
final GlobalKey<NavigatorState> navigatorKey;
final GlobalKey<NavigatorState>? navigatorKey;
/// {@macro flutter.widgets.widgetsApp.home}
final Widget home;
final Widget? home;
/// The top-level [CupertinoTheme] styling.
///
/// A null [theme] or unspecified [theme] attributes will default to iOS
/// system values.
final CupertinoThemeData theme;
final CupertinoThemeData? theme;
/// The application's top-level routing table.
///
@ -170,37 +168,37 @@ class CupertinoApp extends StatefulWidget {
/// an appropriate transition, including [Hero] animations, to the new route.
///
/// {@macro flutter.widgets.widgetsApp.routes}
final Map<String, WidgetBuilder> routes;
final Map<String, WidgetBuilder>? routes;
/// {@macro flutter.widgets.widgetsApp.initialRoute}
final String initialRoute;
final String? initialRoute;
/// {@macro flutter.widgets.widgetsApp.onGenerateRoute}
final RouteFactory onGenerateRoute;
final RouteFactory? onGenerateRoute;
/// {@macro flutter.widgets.widgetsApp.onGenerateInitialRoutes}
final InitialRouteListFactory onGenerateInitialRoutes;
final InitialRouteListFactory? onGenerateInitialRoutes;
/// {@macro flutter.widgets.widgetsApp.onUnknownRoute}
final RouteFactory onUnknownRoute;
final RouteFactory? onUnknownRoute;
/// {@macro flutter.widgets.widgetsApp.navigatorObservers}
final List<NavigatorObserver> navigatorObservers;
final List<NavigatorObserver>? navigatorObservers;
/// {@macro flutter.widgets.widgetsApp.routeInformationProvider}
final RouteInformationProvider routeInformationProvider;
final RouteInformationProvider? routeInformationProvider;
/// {@macro flutter.widgets.widgetsApp.routeInformationParser}
final RouteInformationParser<Object> routeInformationParser;
final RouteInformationParser<Object>? routeInformationParser;
/// {@macro flutter.widgets.widgetsApp.routerDelegate}
final RouterDelegate<Object> routerDelegate;
final RouterDelegate<Object>? routerDelegate;
/// {@macro flutter.widgets.widgetsApp.backButtonDispatcher}
final BackButtonDispatcher backButtonDispatcher;
final BackButtonDispatcher? backButtonDispatcher;
/// {@macro flutter.widgets.widgetsApp.builder}
final TransitionBuilder builder;
final TransitionBuilder? builder;
/// {@macro flutter.widgets.widgetsApp.title}
///
@ -210,26 +208,26 @@ class CupertinoApp extends StatefulWidget {
/// {@macro flutter.widgets.widgetsApp.onGenerateTitle}
///
/// This value is passed unmodified to [WidgetsApp.onGenerateTitle].
final GenerateAppTitle onGenerateTitle;
final GenerateAppTitle? onGenerateTitle;
/// {@macro flutter.widgets.widgetsApp.color}
final Color color;
final Color? color;
/// {@macro flutter.widgets.widgetsApp.locale}
final Locale locale;
final Locale? locale;
/// {@macro flutter.widgets.widgetsApp.localizationsDelegates}
final Iterable<LocalizationsDelegate<dynamic>> localizationsDelegates;
final Iterable<LocalizationsDelegate<dynamic>>? localizationsDelegates;
/// {@macro flutter.widgets.widgetsApp.localeListResolutionCallback}
///
/// This callback is passed along to the [WidgetsApp] built by this widget.
final LocaleListResolutionCallback localeListResolutionCallback;
final LocaleListResolutionCallback? localeListResolutionCallback;
/// {@macro flutter.widgets.widgetsApp.localeResolutionCallback}
///
/// This callback is passed along to the [WidgetsApp] built by this widget.
final LocaleResolutionCallback localeResolutionCallback;
final LocaleResolutionCallback? localeResolutionCallback;
/// {@macro flutter.widgets.widgetsApp.supportedLocales}
///
@ -282,7 +280,7 @@ class CupertinoApp extends StatefulWidget {
/// ```
/// {@end-tool}
/// {@macro flutter.widgets.widgetsApp.shortcuts.seeAlso}
final Map<LogicalKeySet, Intent> shortcuts;
final Map<LogicalKeySet, Intent>? shortcuts;
/// {@macro flutter.widgets.widgetsApp.actions}
/// {@tool snippet}
@ -315,7 +313,7 @@ class CupertinoApp extends StatefulWidget {
/// ```
/// {@end-tool}
/// {@macro flutter.widgets.widgetsApp.actions.seeAlso}
final Map<Type, Action<Intent>> actions;
final Map<Type, Action<Intent>>? actions;
@override
_CupertinoAppState createState() => _CupertinoAppState();
@ -341,7 +339,7 @@ class _AlwaysCupertinoScrollBehavior extends ScrollBehavior {
}
class _CupertinoAppState extends State<CupertinoApp> {
HeroController _heroController;
late HeroController _heroController;
bool get _usesRouter => widget.routerDelegate != null;
@override
@ -357,7 +355,7 @@ class _CupertinoAppState extends State<CupertinoApp> {
// _CupertinoLocalizationsDelegate.
Iterable<LocalizationsDelegate<dynamic>> get _localizationsDelegates sync* {
if (widget.localizationsDelegates != null)
yield* widget.localizationsDelegates;
yield* widget.localizationsDelegates!;
yield DefaultCupertinoLocalizations.delegate;
}
@ -375,14 +373,14 @@ class _CupertinoAppState extends State<CupertinoApp> {
WidgetsApp _buildWidgetApp(BuildContext context) {
final CupertinoThemeData effectiveThemeData = CupertinoTheme.of(context);
final Color color = CupertinoDynamicColor.resolve(widget.color ?? effectiveThemeData.primaryColor, context);
final Color color = CupertinoDynamicColor.resolve(widget.color ?? effectiveThemeData.primaryColor, context)!;
if (_usesRouter) {
return WidgetsApp.router(
key: GlobalObjectKey(this),
routeInformationProvider: widget.routeInformationProvider,
routeInformationParser: widget.routeInformationParser,
routerDelegate: widget.routerDelegate,
routeInformationParser: widget.routeInformationParser!,
routerDelegate: widget.routerDelegate!,
backButtonDispatcher: widget.backButtonDispatcher,
builder: widget.builder,
title: widget.title,
@ -407,12 +405,12 @@ class _CupertinoAppState extends State<CupertinoApp> {
return WidgetsApp(
key: GlobalObjectKey(this),
navigatorKey: widget.navigatorKey,
navigatorObservers: widget.navigatorObservers,
navigatorObservers: widget.navigatorObservers!,
pageRouteBuilder: <T>(RouteSettings settings, WidgetBuilder builder) {
return CupertinoPageRoute<T>(settings: settings, builder: builder);
},
home: widget.home,
routes: widget.routes,
routes: widget.routes!,
initialRoute: widget.initialRoute,
onGenerateRoute: widget.onGenerateRoute,
onGenerateInitialRoutes: widget.onGenerateInitialRoutes,

View file

@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:ui' show ImageFilter;
import 'package:flutter/widgets.dart';
@ -53,8 +51,8 @@ const Color _kDefaultTabBarInactiveColor = CupertinoColors.inactiveGray;
class CupertinoTabBar extends StatelessWidget implements PreferredSizeWidget {
/// Creates a tab bar in the iOS style.
const CupertinoTabBar({
Key key,
@required this.items,
Key? key,
required this.items,
this.onTap,
this.currentIndex = 0,
this.backgroundColor,
@ -89,7 +87,7 @@ class CupertinoTabBar extends StatelessWidget implements PreferredSizeWidget {
/// The widget creating the bottom navigation bar needs to keep track of the
/// current index and call `setState` to rebuild it with the newly provided
/// index.
final ValueChanged<int> onTap;
final ValueChanged<int>? onTap;
/// The index into [items] of the current active item.
///
@ -102,13 +100,13 @@ class CupertinoTabBar extends StatelessWidget implements PreferredSizeWidget {
/// behind it.
///
/// Defaults to [CupertinoTheme]'s `barBackgroundColor` when null.
final Color backgroundColor;
final Color? backgroundColor;
/// The foreground color of the icon and title for the [BottomNavigationBarItem]
/// of the selected tab.
///
/// Defaults to [CupertinoTheme]'s `primaryColor` if null.
final Color activeColor;
final Color? activeColor;
/// The foreground color of the icon and title for the [BottomNavigationBarItem]s
/// in the unselected state.
@ -129,7 +127,7 @@ class CupertinoTabBar extends StatelessWidget implements PreferredSizeWidget {
/// The border of the [CupertinoTabBar].
///
/// The default value is a one physical pixel top border with grey color.
final Border border;
final Border? border;
@override
Size get preferredSize => const Size.fromHeight(_kTabBarHeight);
@ -139,14 +137,15 @@ class CupertinoTabBar extends StatelessWidget implements PreferredSizeWidget {
bool opaque(BuildContext context) {
final Color backgroundColor =
this.backgroundColor ?? CupertinoTheme.of(context).barBackgroundColor;
return CupertinoDynamicColor.resolve(backgroundColor, context).alpha == 0xFF;
return CupertinoDynamicColor.resolve(backgroundColor, context)!.alpha == 0xFF;
}
@override
Widget build(BuildContext context) {
final double bottomPadding = MediaQuery.of(context).padding.bottom;
assert(debugCheckHasMediaQuery(context));
final double bottomPadding = MediaQuery.of(context)!.padding.bottom;
final Color backgroundColor = CupertinoDynamicColor.resolve(
final Color? backgroundColor = CupertinoDynamicColor.resolve(
this.backgroundColor ?? CupertinoTheme.of(context).barBackgroundColor,
context,
);
@ -158,16 +157,16 @@ class CupertinoTabBar extends StatelessWidget implements PreferredSizeWidget {
}
// Return the border as is when it's a subclass.
final Border resolvedBorder = border == null || border.runtimeType != Border
final Border? resolvedBorder = border == null || border.runtimeType != Border
? border
: Border(
top: resolveBorderSide(border.top),
left: resolveBorderSide(border.left),
bottom: resolveBorderSide(border.bottom),
right: resolveBorderSide(border.right),
top: resolveBorderSide(border!.top),
left: resolveBorderSide(border!.left),
bottom: resolveBorderSide(border!.bottom),
right: resolveBorderSide(border!.right),
);
final Color inactive = CupertinoDynamicColor.resolve(inactiveColor, context);
final Color? inactive = CupertinoDynamicColor.resolve(inactiveColor, context);
Widget result = DecoratedBox(
decoration: BoxDecoration(
border: resolvedBorder,
@ -210,7 +209,7 @@ class CupertinoTabBar extends StatelessWidget implements PreferredSizeWidget {
List<Widget> _buildTabItems(BuildContext context) {
final List<Widget> result = <Widget>[];
final CupertinoLocalizations localizations = CupertinoLocalizations.of(context);
final CupertinoLocalizations? localizations = CupertinoLocalizations.of(context);
assert(
localizations != null,
'CupertinoTabBar requires a Localizations parent in order to provide an '
@ -227,13 +226,13 @@ class CupertinoTabBar extends StatelessWidget implements PreferredSizeWidget {
Expanded(
child: Semantics(
selected: active,
hint: localizations.tabSemanticsLabel(
hint: localizations!.tabSemanticsLabel(
tabIndex: index + 1,
tabCount: items.length,
),
child: GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: onTap == null ? null : () { onTap(index); },
onTap: onTap == null ? null : () { onTap!(index); },
child: Padding(
padding: const EdgeInsets.only(bottom: 4.0),
child: Column(
@ -257,17 +256,17 @@ class CupertinoTabBar extends StatelessWidget implements PreferredSizeWidget {
Expanded(
child: Center(child: active ? item.activeIcon : item.icon),
),
if (item.title != null) item.title,
if (item.label != null) Text(item.label),
if (item.title != null) item.title!,
if (item.label != null) Text(item.label!),
];
}
/// Change the active tab item's icon and title colors to active.
Widget _wrapActiveItem(BuildContext context, Widget item, { @required bool active }) {
Widget _wrapActiveItem(BuildContext context, Widget item, { required bool active }) {
if (!active)
return item;
final Color activeColor = CupertinoDynamicColor.resolve(
final Color? activeColor = CupertinoDynamicColor.resolve(
this.activeColor ?? CupertinoTheme.of(context).primaryColor,
context,
);
@ -283,15 +282,15 @@ class CupertinoTabBar extends StatelessWidget implements PreferredSizeWidget {
/// Create a clone of the current [CupertinoTabBar] but with provided
/// parameters overridden.
CupertinoTabBar copyWith({
Key key,
List<BottomNavigationBarItem> items,
Color backgroundColor,
Color activeColor,
Color inactiveColor,
double iconSize,
Border border,
int currentIndex,
ValueChanged<int> onTap,
Key? key,
List<BottomNavigationBarItem>? items,
Color? backgroundColor,
Color? activeColor,
Color? inactiveColor,
double? iconSize,
Border? border,
int? currentIndex,
ValueChanged<int>? onTap,
}) {
return CupertinoTabBar(
key: key ?? this.key,

View file

@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:math' as math;
import 'dart:ui' as ui;
import 'package:flutter/gestures.dart' show kMinFlingVelocity, kLongPressTimeout;
@ -42,7 +40,7 @@ typedef _ContextMenuPreviewBuilderChildless = Widget Function(
// paintBounds in global coordinates.
Rect _getRect(GlobalKey globalKey) {
assert(globalKey.currentContext != null);
final RenderBox renderBoxContainer = globalKey.currentContext.findRenderObject() as RenderBox;
final RenderBox renderBoxContainer = globalKey.currentContext!.findRenderObject() as RenderBox;
final Offset containerOffset = renderBoxContainer.localToGlobal(
renderBoxContainer.paintBounds.topLeft,
);
@ -129,9 +127,9 @@ class CupertinoContextMenu extends StatefulWidget {
///
/// [child] is required and cannot be null.
CupertinoContextMenu({
Key key,
@required this.actions,
@required this.child,
Key? key,
required this.actions,
required this.child,
this.previewBuilder,
}) : assert(actions != null && actions.isNotEmpty),
assert(child != null),
@ -220,7 +218,7 @@ class CupertinoContextMenu extends StatefulWidget {
/// ```
///
/// {@end-tool}
final ContextMenuPreviewBuilder previewBuilder;
final ContextMenuPreviewBuilder? previewBuilder;
@override
_CupertinoContextMenuState createState() => _CupertinoContextMenuState();
@ -230,10 +228,10 @@ class _CupertinoContextMenuState extends State<CupertinoContextMenu> with Ticker
final GlobalKey _childGlobalKey = GlobalKey();
bool _childHidden = false;
// Animates the child while it's opening.
AnimationController _openController;
Rect _decoyChildEndRect;
OverlayEntry _lastOverlayEntry;
_ContextMenuRoute<void> _route;
late AnimationController _openController;
Rect? _decoyChildEndRect;
OverlayEntry? _lastOverlayEntry;
_ContextMenuRoute<void>? _route;
@override
void initState() {
@ -255,7 +253,7 @@ class _CupertinoContextMenuState extends State<CupertinoContextMenu> with Ticker
// it.
_ContextMenuLocation get _contextMenuLocation {
final Rect childRect = _getRect(_childGlobalKey);
final double screenWidth = MediaQuery.of(context).size.width;
final double screenWidth = MediaQuery.of(context)!.size.width;
final double center = screenWidth / 2;
final bool centerDividesChild = childRect.left < center
@ -286,16 +284,16 @@ class _CupertinoContextMenuState extends State<CupertinoContextMenu> with Ticker
sigmaY: 5.0,
),
contextMenuLocation: _contextMenuLocation,
previousChildRect: _decoyChildEndRect,
previousChildRect: _decoyChildEndRect!,
builder: (BuildContext context, Animation<double> animation) {
if (widget.previewBuilder == null) {
return widget.child;
}
return widget.previewBuilder(context, animation, widget.child);
return widget.previewBuilder!(context, animation, widget.child);
},
);
Navigator.of(context, rootNavigator: true).push<void>(_route);
_route.animation.addStatusListener(_routeAnimationStatusListener);
Navigator.of(context, rootNavigator: true)!.push<void>(_route!);
_route!.animation!.addStatusListener(_routeAnimationStatusListener);
}
void _onDecoyAnimationStatusChange(AnimationStatus animationStatus) {
@ -319,7 +317,7 @@ class _CupertinoContextMenuState extends State<CupertinoContextMenu> with Ticker
// because _ContextMenuRoute renders its first frame offscreen.
// Otherwise there would be a visible flash when nothing is rendered for
// one frame.
SchedulerBinding.instance.addPostFrameCallback((Duration _) {
SchedulerBinding.instance!.addPostFrameCallback((Duration _) {
_lastOverlayEntry?.remove();
_lastOverlayEntry = null;
_openController.reset();
@ -340,7 +338,7 @@ class _CupertinoContextMenuState extends State<CupertinoContextMenu> with Ticker
setState(() {
_childHidden = false;
});
_route.animation.removeStatusListener(_routeAnimationStatusListener);
_route!.animation!.removeStatusListener(_routeAnimationStatusListener);
_route = null;
}
@ -393,7 +391,7 @@ class _CupertinoContextMenuState extends State<CupertinoContextMenu> with Ticker
);
},
);
Overlay.of(context).insert(_lastOverlayEntry);
Overlay.of(context)!.insert(_lastOverlayEntry!);
_openController.forward();
}
@ -431,17 +429,17 @@ class _CupertinoContextMenuState extends State<CupertinoContextMenu> with Ticker
// siblings of the original child.
class _DecoyChild extends StatefulWidget {
const _DecoyChild({
Key key,
Key? key,
this.beginRect,
this.controller,
required this.controller,
this.endRect,
this.child,
}) : super(key: key);
final Rect beginRect;
final Rect? beginRect;
final AnimationController controller;
final Rect endRect;
final Widget child;
final Rect? endRect;
final Widget? child;
@override
_DecoyChildState createState() => _DecoyChildState();
@ -454,8 +452,8 @@ class _DecoyChildState extends State<_DecoyChild> with TickerProviderStateMixin
static const Color _masklessColor = Color(0xFFFFFFFF);
final GlobalKey _childGlobalKey = GlobalKey();
Animation<Color> _mask;
Animation<Rect> _rect;
late Animation<Color> _mask;
late Animation<Rect?> _rect;
@override
void initState() {
@ -470,18 +468,18 @@ class _DecoyChildState extends State<_DecoyChild> with TickerProviderStateMixin
intervalOff: 0.5,
);
final Rect midRect = widget.beginRect.deflate(
widget.beginRect.width * (_kOpenScale - 1.0) / 2,
final Rect midRect = widget.beginRect!.deflate(
widget.beginRect!.width * (_kOpenScale - 1.0) / 2,
);
_rect = TweenSequence<Rect>(<TweenSequenceItem<Rect>>[
TweenSequenceItem<Rect>(
_rect = TweenSequence<Rect?>(<TweenSequenceItem<Rect?>>[
TweenSequenceItem<Rect?>(
tween: RectTween(
begin: widget.beginRect,
end: midRect,
).chain(CurveTween(curve: Curves.easeInOutCubic)),
weight: 1.0,
),
TweenSequenceItem<Rect>(
TweenSequenceItem<Rect?>(
tween: RectTween(
begin: midRect,
end: widget.endRect,
@ -508,12 +506,12 @@ class _DecoyChildState extends State<_DecoyChild> with TickerProviderStateMixin
super.dispose();
}
Widget _buildAnimation(BuildContext context, Widget child) {
Widget _buildAnimation(BuildContext context, Widget? child) {
final Color color = widget.controller.status == AnimationStatus.reverse
? _masklessColor
: _mask.value;
return Positioned.fromRect(
rect: _rect.value,
rect: _rect.value!,
// TODO(justinmc): When ShaderMask is supported on web, remove this
// conditional and use ShaderMask everywhere.
// https://github.com/flutter/flutter/issues/52967.
@ -550,13 +548,13 @@ class _DecoyChildState extends State<_DecoyChild> with TickerProviderStateMixin
class _ContextMenuRoute<T> extends PopupRoute<T> {
// Build a _ContextMenuRoute.
_ContextMenuRoute({
@required List<Widget> actions,
@required _ContextMenuLocation contextMenuLocation,
required List<Widget> actions,
required _ContextMenuLocation contextMenuLocation,
this.barrierLabel,
_ContextMenuPreviewBuilderChildless builder,
ui.ImageFilter filter,
Rect previousChildRect,
RouteSettings settings,
_ContextMenuPreviewBuilderChildless? builder,
ui.ImageFilter? filter,
required Rect previousChildRect,
RouteSettings? settings,
}) : assert(actions != null && actions.isNotEmpty),
assert(contextMenuLocation != null),
_actions = actions,
@ -576,15 +574,15 @@ class _ContextMenuRoute<T> extends PopupRoute<T> {
Duration(milliseconds: 335);
final List<Widget> _actions;
final _ContextMenuPreviewBuilderChildless _builder;
final _ContextMenuPreviewBuilderChildless? _builder;
final GlobalKey _childGlobalKey = GlobalKey();
final _ContextMenuLocation _contextMenuLocation;
bool _externalOffstage = false;
bool _internalOffstage = false;
Orientation _lastOrientation;
Orientation? _lastOrientation;
// The Rect of the child at the moment that the CupertinoContextMenu opens.
final Rect _previousChildRect;
double _scale = 1.0;
double? _scale = 1.0;
final GlobalKey _sheetGlobalKey = GlobalKey();
static final CurveTween _curve = CurveTween(
@ -594,17 +592,17 @@ class _ContextMenuRoute<T> extends PopupRoute<T> {
curve: Curves.easeInBack,
);
static final RectTween _rectTween = RectTween();
static final Animatable<Rect> _rectAnimatable = _rectTween.chain(_curve);
static final Animatable<Rect?> _rectAnimatable = _rectTween.chain(_curve);
static final RectTween _rectTweenReverse = RectTween();
static final Animatable<Rect> _rectAnimatableReverse = _rectTweenReverse
static final Animatable<Rect?> _rectAnimatableReverse = _rectTweenReverse
.chain(
_curveReverse,
);
static final RectTween _sheetRectTween = RectTween();
final Animatable<Rect> _sheetRectAnimatable = _sheetRectTween.chain(
final Animatable<Rect?> _sheetRectAnimatable = _sheetRectTween.chain(
_curve,
);
final Animatable<Rect> _sheetRectAnimatableReverse = _sheetRectTween.chain(
final Animatable<Rect?> _sheetRectAnimatableReverse = _sheetRectTween.chain(
_curveReverse,
);
static final Tween<double> _sheetScaleTween = Tween<double>();
@ -617,10 +615,10 @@ class _ContextMenuRoute<T> extends PopupRoute<T> {
_curveReverse,
);
final Tween<double> _opacityTween = Tween<double>(begin: 0.0, end: 1.0);
Animation<double> _sheetOpacity;
late Animation<double> _sheetOpacity;
@override
final String barrierLabel;
final String? barrierLabel;
@override
Color get barrierColor => _kModalBarrierColor;
@ -660,7 +658,7 @@ class _ContextMenuRoute<T> extends PopupRoute<T> {
}
// The place to start the sheetRect animation from.
static Rect _getSheetRectBegin(Orientation orientation, _ContextMenuLocation contextMenuLocation, Rect childRect, Rect sheetRect) {
static Rect _getSheetRectBegin(Orientation? orientation, _ContextMenuLocation contextMenuLocation, Rect childRect, Rect sheetRect) {
switch (contextMenuLocation) {
case _ContextMenuLocation.center:
final Offset target = orientation == Orientation.portrait
@ -685,10 +683,10 @@ class _ContextMenuRoute<T> extends PopupRoute<T> {
_scale = scale;
_opacityTween.end = opacity;
_sheetOpacity = _opacityTween.animate(CurvedAnimation(
parent: animation,
parent: animation!,
curve: const Interval(0.9, 1.0),
));
Navigator.of(context).pop();
Navigator.of(context)!.pop();
}
// Take measurements on the child and _ContextMenuSheet and update the
@ -696,7 +694,7 @@ class _ContextMenuRoute<T> extends PopupRoute<T> {
void _updateTweenRects() {
final Rect childRect = _scale == null
? _getRect(_childGlobalKey)
: _getScaledRect(_childGlobalKey, _scale);
: _getScaledRect(_childGlobalKey, _scale!);
_rectTween.begin = _previousChildRect;
_rectTween.end = childRect;
@ -751,7 +749,7 @@ class _ContextMenuRoute<T> extends PopupRoute<T> {
// Render one frame offstage in the final position so that we can take
// measurements of its layout and then animate to them.
SchedulerBinding.instance.addPostFrameCallback((Duration _) {
SchedulerBinding.instance!.addPostFrameCallback((Duration _) {
_updateTweenRects();
_internalOffstage = false;
_setOffstageInternally();
@ -775,8 +773,8 @@ class _ContextMenuRoute<T> extends PopupRoute<T> {
// buildTransitions as child, the idea being that buildTransitions will
// animate the entire page into the scene. In the case of _ContextMenuRoute,
// two individual pieces of the page are animated into the scene in
// buildTransitions, and null is returned here.
return null;
// buildTransitions, and a Container is returned here.
return Container();
}
@override
@ -790,11 +788,11 @@ class _ContextMenuRoute<T> extends PopupRoute<T> {
if (!animation.isCompleted) {
final bool reverse = animation.status == AnimationStatus.reverse;
final Rect rect = reverse
? _rectAnimatableReverse.evaluate(animation)
: _rectAnimatable.evaluate(animation);
? _rectAnimatableReverse.evaluate(animation)!
: _rectAnimatable.evaluate(animation)!;
final Rect sheetRect = reverse
? _sheetRectAnimatableReverse.evaluate(animation)
: _sheetRectAnimatable.evaluate(animation);
? _sheetRectAnimatableReverse.evaluate(animation)!
: _sheetRectAnimatable.evaluate(animation)!;
final double sheetScale = reverse
? _sheetScaleAnimatableReverse.evaluate(animation)
: _sheetScaleAnimatable.evaluate(animation);
@ -819,7 +817,7 @@ class _ContextMenuRoute<T> extends PopupRoute<T> {
Positioned.fromRect(
key: _childGlobalKey,
rect: rect,
child: _builder(context, animation),
child: _builder!(context, animation),
),
],
);
@ -829,7 +827,7 @@ class _ContextMenuRoute<T> extends PopupRoute<T> {
// in the final position.
return _ContextMenuRouteStatic(
actions: _actions,
child: _builder(context, animation),
child: _builder!(context, animation),
childGlobalKey: _childGlobalKey,
contextMenuLocation: _contextMenuLocation,
onDismiss: _onDismiss,
@ -845,25 +843,25 @@ class _ContextMenuRoute<T> extends PopupRoute<T> {
// animating out.
class _ContextMenuRouteStatic extends StatefulWidget {
const _ContextMenuRouteStatic({
Key key,
Key? key,
this.actions,
@required this.child,
required this.child,
this.childGlobalKey,
@required this.contextMenuLocation,
required this.contextMenuLocation,
this.onDismiss,
@required this.orientation,
required this.orientation,
this.sheetGlobalKey,
}) : assert(contextMenuLocation != null),
assert(orientation != null),
super(key: key);
final List<Widget> actions;
final List<Widget>? actions;
final Widget child;
final GlobalKey childGlobalKey;
final GlobalKey? childGlobalKey;
final _ContextMenuLocation contextMenuLocation;
final _DismissCallback onDismiss;
final _DismissCallback? onDismiss;
final Orientation orientation;
final GlobalKey sheetGlobalKey;
final GlobalKey? sheetGlobalKey;
@override
_ContextMenuRouteStaticState createState() => _ContextMenuRouteStaticState();
@ -879,13 +877,13 @@ class _ContextMenuRouteStaticState extends State<_ContextMenuRouteStatic> with T
static const double _kDamping = 400.0;
static const Duration _kMoveControllerDuration = Duration(milliseconds: 600);
Offset _dragOffset;
late Offset _dragOffset;
double _lastScale = 1.0;
AnimationController _moveController;
AnimationController _sheetController;
Animation<Offset> _moveAnimation;
Animation<double> _sheetScaleAnimation;
Animation<double> _sheetOpacityAnimation;
late AnimationController _moveController;
late AnimationController _sheetController;
late Animation<Offset> _moveAnimation;
late Animation<double> _sheetScaleAnimation;
late Animation<double> _sheetOpacityAnimation;
// The scale of the child changes as a function of the distance it is dragged.
static double _getScale(Orientation orientation, double maxDragDistance, double dy) {
@ -934,7 +932,7 @@ class _ContextMenuRouteStaticState extends State<_ContextMenuRouteStatic> with T
// Dismiss if the drag is enough to scale down all the way.
if (_lastScale == _kMinScale) {
widget.onDismiss(context, _lastScale, _sheetOpacityAnimation.value);
widget.onDismiss!(context, _lastScale, _sheetOpacityAnimation.value);
return;
}
@ -967,7 +965,7 @@ class _ContextMenuRouteStaticState extends State<_ContextMenuRouteStatic> with T
if (_moveAnimation.value.dy == 0.0) {
return;
}
widget.onDismiss(context, _lastScale, _sheetOpacityAnimation.value);
widget.onDismiss!(context, _lastScale, _sheetOpacityAnimation.value);
}
Alignment _getChildAlignment(Orientation orientation, _ContextMenuLocation contextMenuLocation) {
@ -998,7 +996,7 @@ class _ContextMenuRouteStaticState extends State<_ContextMenuRouteStatic> with T
_moveAnimation = Tween<Offset>(
begin: Offset.zero,
end: Offset(
endX.clamp(-_kPadding, _kPadding) as double,
endX.clamp(-_kPadding, _kPadding),
endY,
),
).animate(
@ -1048,7 +1046,7 @@ class _ContextMenuRouteStaticState extends State<_ContextMenuRouteStatic> with T
builder: _buildSheetAnimation,
child: _ContextMenuSheet(
key: widget.sheetGlobalKey,
actions: widget.actions,
actions: widget.actions!,
contextMenuLocation: widget.contextMenuLocation,
orientation: widget.orientation,
),
@ -1068,7 +1066,7 @@ class _ContextMenuRouteStaticState extends State<_ContextMenuRouteStatic> with T
}
// Build the animation for the _ContextMenuSheet.
Widget _buildSheetAnimation(BuildContext context, Widget child) {
Widget _buildSheetAnimation(BuildContext context, Widget? child) {
return Transform.scale(
alignment: _ContextMenuRoute.getSheetAlignment(widget.contextMenuLocation),
scale: _sheetScaleAnimation.value,
@ -1080,10 +1078,10 @@ class _ContextMenuRouteStaticState extends State<_ContextMenuRouteStatic> with T
}
// Build the animation for the child.
Widget _buildChildAnimation(BuildContext context, Widget child) {
Widget _buildChildAnimation(BuildContext context, Widget? child) {
_lastScale = _getScale(
widget.orientation,
MediaQuery.of(context).size.height,
MediaQuery.of(context)!.size.height,
_moveAnimation.value.dy,
);
return Transform.scale(
@ -1094,7 +1092,7 @@ class _ContextMenuRouteStaticState extends State<_ContextMenuRouteStatic> with T
}
// Build the animation for the overall draggable dismissible content.
Widget _buildAnimation(BuildContext context, Widget child) {
Widget _buildAnimation(BuildContext context, Widget? child) {
return Transform.translate(
offset: _moveAnimation.value,
child: child,
@ -1178,10 +1176,10 @@ class _ContextMenuRouteStaticState extends State<_ContextMenuRouteStatic> with T
// list of actions that are typically CupertinoContextMenuActions.
class _ContextMenuSheet extends StatelessWidget {
_ContextMenuSheet({
Key key,
@required this.actions,
@required _ContextMenuLocation contextMenuLocation,
@required Orientation orientation,
Key? key,
required this.actions,
required _ContextMenuLocation contextMenuLocation,
required Orientation orientation,
}) : assert(actions != null && actions.isNotEmpty),
assert(contextMenuLocation != null),
assert(orientation != null),
@ -1261,11 +1259,11 @@ class _ContextMenuSheet extends StatelessWidget {
// offColor at the times given by intervalOn and intervalOff.
class _OnOffAnimation<T> extends CompoundAnimation<T> {
_OnOffAnimation({
AnimationController controller,
@required T onValue,
@required T offValue,
@required double intervalOn,
@required double intervalOff,
required AnimationController controller,
required T onValue,
required T offValue,
required double intervalOn,
required double intervalOff,
}) : _offValue = offValue,
assert(intervalOn >= 0.0 && intervalOn <= 1.0),
assert(intervalOff >= 0.0 && intervalOff <= 1.0),

View file

@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';
import 'colors.dart';
@ -16,8 +14,8 @@ import 'colors.dart';
class CupertinoContextMenuAction extends StatefulWidget {
/// Construct a CupertinoContextMenuAction.
const CupertinoContextMenuAction({
Key key,
@required this.child,
Key? key,
required this.child,
this.isDefaultAction = false,
this.isDestructiveAction = false,
this.onPressed,
@ -39,13 +37,13 @@ class CupertinoContextMenuAction extends StatefulWidget {
final bool isDestructiveAction;
/// Called when the action is pressed.
final VoidCallback onPressed;
final VoidCallback? onPressed;
/// An optional icon to display to the right of the child.
///
/// Will be colored in the same way as the [TextStyle] used for [child] (for
/// example, if using [isDestructiveAction]).
final IconData trailingIcon;
final IconData? trailingIcon;
@override
_CupertinoContextMenuActionState createState() => _CupertinoContextMenuActionState();

View file

@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:math' as math;
import 'package:flutter/scheduler.dart';
@ -67,8 +65,8 @@ void _animateColumnControllerToItem(FixedExtentScrollController controller, int
// column will be extended equally to the remaining width.
class _DatePickerLayoutDelegate extends MultiChildLayoutDelegate {
_DatePickerLayoutDelegate({
@required this.columnWidths,
@required this.textDirectionFactor,
required this.columnWidths,
required this.textDirectionFactor,
}) : assert(columnWidths != null),
assert(textDirectionFactor != null);
@ -236,10 +234,10 @@ class CupertinoDatePicker extends StatefulWidget {
///
/// [use24hFormat] decides whether 24 hour format is used. Defaults to false.
CupertinoDatePicker({
Key key,
Key? key,
this.mode = CupertinoDatePickerMode.dateAndTime,
@required this.onDateTimeChanged,
DateTime initialDateTime,
required this.onDateTimeChanged,
DateTime? initialDateTime,
this.minimumDate,
this.maximumDate,
this.minimumYear = 1,
@ -258,11 +256,11 @@ class CupertinoDatePicker extends StatefulWidget {
super(key: key) {
assert(this.initialDateTime != null);
assert(
mode != CupertinoDatePickerMode.dateAndTime || minimumDate == null || !this.initialDateTime.isBefore(minimumDate),
mode != CupertinoDatePickerMode.dateAndTime || minimumDate == null || !this.initialDateTime.isBefore(minimumDate!),
'initial date is before minimum date',
);
assert(
mode != CupertinoDatePickerMode.dateAndTime || maximumDate == null || !this.initialDateTime.isAfter(maximumDate),
mode != CupertinoDatePickerMode.dateAndTime || maximumDate == null || !this.initialDateTime.isAfter(maximumDate!),
'initial date is after maximum date',
);
assert(
@ -270,15 +268,15 @@ class CupertinoDatePicker extends StatefulWidget {
'initial year is not greater than minimum year, or minimum year is not positive',
);
assert(
mode != CupertinoDatePickerMode.date || maximumYear == null || this.initialDateTime.year <= maximumYear,
mode != CupertinoDatePickerMode.date || maximumYear == null || this.initialDateTime.year <= maximumYear!,
'initial year is not smaller than maximum year',
);
assert(
mode != CupertinoDatePickerMode.date || minimumDate == null || !minimumDate.isAfter(this.initialDateTime),
mode != CupertinoDatePickerMode.date || minimumDate == null || !minimumDate!.isAfter(this.initialDateTime),
'initial date ${this.initialDateTime} is not greater than or equal to minimumDate $minimumDate',
);
assert(
mode != CupertinoDatePickerMode.date || maximumDate == null || !maximumDate.isBefore(this.initialDateTime),
mode != CupertinoDatePickerMode.date || maximumDate == null || !maximumDate!.isBefore(this.initialDateTime),
'initial date ${this.initialDateTime} is not less than or equal to maximumDate $maximumDate',
);
assert(
@ -313,7 +311,7 @@ class CupertinoDatePicker extends StatefulWidget {
///
/// Defaults to null. When set to null, the picker does not impose a limit on
/// the earliest [DateTime] the user can select.
final DateTime minimumDate;
final DateTime? minimumDate;
/// The maximum selectable date that the picker can settle on.
///
@ -328,7 +326,7 @@ class CupertinoDatePicker extends StatefulWidget {
///
/// Defaults to null. When set to null, the picker does not impose a limit on
/// the latest [DateTime] the user can select.
final DateTime maximumDate;
final DateTime? maximumDate;
/// Minimum year that the picker can be scrolled to in
/// [CupertinoDatePickerMode.date] mode. Defaults to 1 and must not be null.
@ -336,7 +334,7 @@ class CupertinoDatePicker extends StatefulWidget {
/// Maximum year that the picker can be scrolled to in
/// [CupertinoDatePickerMode.date] mode. Null if there's no limit.
final int maximumYear;
final int? maximumYear;
/// The granularity of the minutes spinner, if it is shown in the current mode.
/// Must be an integer factor of 60.
@ -355,7 +353,7 @@ class CupertinoDatePicker extends StatefulWidget {
/// Background color of date picker.
///
/// Defaults to null, which disables background painting entirely.
final Color backgroundColor;
final Color? backgroundColor;
@override
State<StatefulWidget> createState() {
@ -370,9 +368,6 @@ class CupertinoDatePicker extends StatefulWidget {
case CupertinoDatePickerMode.date:
return _CupertinoDatePickerDateState();
}
assert(false);
return _CupertinoDatePickerDateTimeState();
}
// Estimate the minimum width that each column needs to layout its content.
@ -460,17 +455,17 @@ class _CupertinoDatePickerDateTimeState extends State<CupertinoDatePicker> {
// vs iOS.
static const double _kMaximumOffAxisFraction = 0.45;
int textDirectionFactor;
CupertinoLocalizations localizations;
late int textDirectionFactor;
late CupertinoLocalizations localizations;
// Alignment based on text direction. The variable name is self descriptive,
// however, when text direction is rtl, alignment is reversed.
Alignment alignCenterLeft;
Alignment alignCenterRight;
late Alignment alignCenterLeft;
late Alignment alignCenterRight;
// Read this out when the state is initially created. Changes in initialDateTime
// in the widget after first build is ignored.
DateTime initialDateTime;
late DateTime initialDateTime;
// The difference in days between the initial date and the currently selected date.
// 0 if the current mode does not involve a date.
@ -490,7 +485,7 @@ class _CupertinoDatePickerDateTimeState extends State<CupertinoDatePicker> {
return 0;
}
// The controller of the date column.
FixedExtentScrollController dateController;
late FixedExtentScrollController dateController;
// The current selection of the hour picker. Values range from 0 to 23.
int get selectedHour => _selectedHour(selectedAmPm, _selectedHourIndex);
@ -501,7 +496,7 @@ class _CupertinoDatePickerDateTimeState extends State<CupertinoDatePicker> {
return _isHourRegionFlipped(selectedAmPm) ? (selectedHour + 12) % 24 : selectedHour;
}
// The controller of the hour column.
FixedExtentScrollController hourController;
late FixedExtentScrollController hourController;
// The current selection of the minute picker. Values range from 0 to 59.
int get selectedMinute {
@ -510,7 +505,7 @@ class _CupertinoDatePickerDateTimeState extends State<CupertinoDatePicker> {
: initialDateTime.minute;
}
// The controller of the minute column.
FixedExtentScrollController minuteController;
late FixedExtentScrollController minuteController;
// Whether the current meridiem selection is AM or PM.
//
@ -518,7 +513,7 @@ class _CupertinoDatePickerDateTimeState extends State<CupertinoDatePicker> {
// because the meridiem picker can be scrolled **animatedly** by the hour picker
// (e.g. if you scroll from 12 to 1 in 12h format), but the meridiem change
// should take effect immediately, **before** the animation finishes.
int selectedAmPm;
late int selectedAmPm;
// Whether the physical-region-to-meridiem mapping is flipped.
bool get isHourRegionFlipped => _isHourRegionFlipped(selectedAmPm);
bool _isHourRegionFlipped(int selectedAmPm) => selectedAmPm != meridiemRegion;
@ -531,12 +526,12 @@ class _CupertinoDatePickerDateTimeState extends State<CupertinoDatePicker> {
// scrolls. This variable is to keep track of the selected "physical"
// (meridiem picker invariant) region of the hour picker. The "physical" region
// of an item of index `i` is `i ~/ 12`.
int meridiemRegion;
late int meridiemRegion;
// The current selection of the AM/PM picker.
//
// - 0 means AM
// - 1 means PM
FixedExtentScrollController meridiemController;
late FixedExtentScrollController meridiemController;
bool isDatePickerScrolling = false;
bool isHourPickerScrolling = false;
@ -570,7 +565,7 @@ class _CupertinoDatePickerDateTimeState extends State<CupertinoDatePicker> {
minuteController = FixedExtentScrollController(initialItem: initialDateTime.minute ~/ widget.minuteInterval);
dateController = FixedExtentScrollController(initialItem: 0);
PaintingBinding.instance.systemFonts.addListener(_handleSystemFontsChange);
PaintingBinding.instance!.systemFonts.addListener(_handleSystemFontsChange);
}
void _handleSystemFontsChange () {
@ -589,7 +584,7 @@ class _CupertinoDatePickerDateTimeState extends State<CupertinoDatePicker> {
minuteController.dispose();
meridiemController.dispose();
PaintingBinding.instance.systemFonts.removeListener(_handleSystemFontsChange);
PaintingBinding.instance!.systemFonts.removeListener(_handleSystemFontsChange);
super.dispose();
}
@ -615,7 +610,7 @@ class _CupertinoDatePickerDateTimeState extends State<CupertinoDatePicker> {
super.didChangeDependencies();
textDirectionFactor = Directionality.of(context) == TextDirection.ltr ? 1 : -1;
localizations = CupertinoLocalizations.of(context);
localizations = CupertinoLocalizations.of(context)!;
alignCenterLeft = textDirectionFactor == 1 ? Alignment.centerLeft : Alignment.centerRight;
alignCenterRight = textDirectionFactor == 1 ? Alignment.centerRight : Alignment.centerLeft;
@ -630,7 +625,7 @@ class _CupertinoDatePickerDateTimeState extends State<CupertinoDatePicker> {
CupertinoDatePicker._getColumnWidth(columnType, localizations, context);
}
return estimatedColumnWidths[columnType.index];
return estimatedColumnWidths[columnType.index]!;
}
// Gets the current date time of the picker.
@ -904,14 +899,14 @@ class _CupertinoDatePickerDateTimeState extends State<CupertinoDatePicker> {
if (minCheck || maxCheck) {
// We have minCheck === !maxCheck.
final DateTime targetDate = minCheck ? widget.minimumDate : widget.maximumDate;
final DateTime targetDate = minCheck ? widget.minimumDate! : widget.maximumDate!;
_scrollToDate(targetDate, selectedDate);
}
}
void _scrollToDate(DateTime newDate, DateTime fromDate) {
assert(newDate != null);
SchedulerBinding.instance.addPostFrameCallback((Duration timestamp) {
SchedulerBinding.instance!.addPostFrameCallback((Duration timestamp) {
if (fromDate.year != newDate.year || fromDate.month != newDate.month || fromDate.day != newDate.day) {
_animateColumnControllerToItem(dateController, selectedDayFromInitial);
}
@ -997,7 +992,7 @@ class _CupertinoDatePickerDateTimeState extends State<CupertinoDatePicker> {
id: i,
child: pickerBuilders[i](
offAxisFraction,
(BuildContext context, Widget child) {
(BuildContext context, Widget? child) {
return Container(
alignment: i == columnWidths.length - 1
? alignCenterLeft
@ -1017,7 +1012,7 @@ class _CupertinoDatePickerDateTimeState extends State<CupertinoDatePicker> {
}
return MediaQuery(
data: MediaQuery.of(context).copyWith(textScaleFactor: 1.0),
data: MediaQuery.of(context)!.copyWith(textScaleFactor: 1.0),
child: DefaultTextStyle.merge(
style: _kDefaultPickerTextStyle,
child: CustomMultiChildLayout(
@ -1033,25 +1028,25 @@ class _CupertinoDatePickerDateTimeState extends State<CupertinoDatePicker> {
}
class _CupertinoDatePickerDateState extends State<CupertinoDatePicker> {
int textDirectionFactor;
CupertinoLocalizations localizations;
late int textDirectionFactor;
late CupertinoLocalizations localizations;
// Alignment based on text direction. The variable name is self descriptive,
// however, when text direction is rtl, alignment is reversed.
Alignment alignCenterLeft;
Alignment alignCenterRight;
late Alignment alignCenterLeft;
late Alignment alignCenterRight;
// The currently selected values of the picker.
int selectedDay;
int selectedMonth;
int selectedYear;
late int selectedDay;
late int selectedMonth;
late int selectedYear;
// The controller of the day picker. There are cases where the selected value
// of the picker is invalid (e.g. February 30th 2018), and this dayController
// is responsible for jumping to a valid value.
FixedExtentScrollController dayController;
FixedExtentScrollController monthController;
FixedExtentScrollController yearController;
late FixedExtentScrollController dayController;
late FixedExtentScrollController monthController;
late FixedExtentScrollController yearController;
bool isDayPickerScrolling = false;
bool isMonthPickerScrolling = false;
@ -1073,7 +1068,7 @@ class _CupertinoDatePickerDateState extends State<CupertinoDatePicker> {
monthController = FixedExtentScrollController(initialItem: selectedMonth - 1);
yearController = FixedExtentScrollController(initialItem: selectedYear);
PaintingBinding.instance.systemFonts.addListener(_handleSystemFontsChange);
PaintingBinding.instance!.systemFonts.addListener(_handleSystemFontsChange);
}
void _handleSystemFontsChange() {
@ -1089,7 +1084,7 @@ class _CupertinoDatePickerDateState extends State<CupertinoDatePicker> {
monthController.dispose();
yearController.dispose();
PaintingBinding.instance.systemFonts.removeListener(_handleSystemFontsChange);
PaintingBinding.instance!.systemFonts.removeListener(_handleSystemFontsChange);
super.dispose();
}
@ -1098,7 +1093,7 @@ class _CupertinoDatePickerDateState extends State<CupertinoDatePicker> {
super.didChangeDependencies();
textDirectionFactor = Directionality.of(context) == TextDirection.ltr ? 1 : -1;
localizations = CupertinoLocalizations.of(context);
localizations = CupertinoLocalizations.of(context)!;
alignCenterLeft = textDirectionFactor == 1 ? Alignment.centerLeft : Alignment.centerRight;
alignCenterRight = textDirectionFactor == 1 ? Alignment.centerRight : Alignment.centerLeft;
@ -1184,8 +1179,8 @@ class _CupertinoDatePickerDateState extends State<CupertinoDatePicker> {
},
children: List<Widget>.generate(12, (int index) {
final int month = index + 1;
final bool isInvalidMonth = (widget.minimumDate?.year == selectedYear && widget.minimumDate.month > month)
|| (widget.maximumDate?.year == selectedYear && widget.maximumDate.month < month);
final bool isInvalidMonth = (widget.minimumDate?.year == selectedYear && widget.minimumDate!.month > month)
|| (widget.maximumDate?.year == selectedYear && widget.maximumDate!.month < month);
return itemPositioningBuilder(
context,
@ -1228,11 +1223,11 @@ class _CupertinoDatePickerDateState extends State<CupertinoDatePicker> {
if (year < widget.minimumYear)
return null;
if (widget.maximumYear != null && year > widget.maximumYear)
if (widget.maximumYear != null && year > widget.maximumYear!)
return null;
final bool isValidYear = (widget.minimumDate == null || widget.minimumDate.year <= year)
&& (widget.maximumDate == null || widget.maximumDate.year >= year);
final bool isValidYear = (widget.minimumDate == null || widget.minimumDate!.year <= year)
&& (widget.maximumDate == null || widget.maximumDate!.year >= year);
return itemPositioningBuilder(
context,
@ -1277,7 +1272,7 @@ class _CupertinoDatePickerDateState extends State<CupertinoDatePicker> {
if (!minCheck || maxCheck) {
// We have minCheck === !maxCheck.
final DateTime targetDate = minCheck ? widget.maximumDate : widget.minimumDate;
final DateTime targetDate = minCheck ? widget.maximumDate! : widget.minimumDate!;
_scrollToDate(targetDate);
return;
}
@ -1292,7 +1287,7 @@ class _CupertinoDatePickerDateState extends State<CupertinoDatePicker> {
void _scrollToDate(DateTime newDate) {
assert(newDate != null);
SchedulerBinding.instance.addPostFrameCallback((Duration timestamp) {
SchedulerBinding.instance!.addPostFrameCallback((Duration timestamp) {
if (selectedYear != newDate.year) {
_animateColumnControllerToItem(yearController, newDate.year);
}
@ -1316,30 +1311,34 @@ class _CupertinoDatePickerDateState extends State<CupertinoDatePicker> {
case DatePickerDateOrder.mdy:
pickerBuilders = <_ColumnBuilder>[_buildMonthPicker, _buildDayPicker, _buildYearPicker];
columnWidths = <double>[
estimatedColumnWidths[_PickerColumnType.month.index],
estimatedColumnWidths[_PickerColumnType.dayOfMonth.index],
estimatedColumnWidths[_PickerColumnType.year.index]];
estimatedColumnWidths[_PickerColumnType.month.index]!,
estimatedColumnWidths[_PickerColumnType.dayOfMonth.index]!,
estimatedColumnWidths[_PickerColumnType.year.index]!,
];
break;
case DatePickerDateOrder.dmy:
pickerBuilders = <_ColumnBuilder>[_buildDayPicker, _buildMonthPicker, _buildYearPicker];
columnWidths = <double>[
estimatedColumnWidths[_PickerColumnType.dayOfMonth.index],
estimatedColumnWidths[_PickerColumnType.month.index],
estimatedColumnWidths[_PickerColumnType.year.index]];
estimatedColumnWidths[_PickerColumnType.dayOfMonth.index]!,
estimatedColumnWidths[_PickerColumnType.month.index]!,
estimatedColumnWidths[_PickerColumnType.year.index]!,
];
break;
case DatePickerDateOrder.ymd:
pickerBuilders = <_ColumnBuilder>[_buildYearPicker, _buildMonthPicker, _buildDayPicker];
columnWidths = <double>[
estimatedColumnWidths[_PickerColumnType.year.index],
estimatedColumnWidths[_PickerColumnType.month.index],
estimatedColumnWidths[_PickerColumnType.dayOfMonth.index]];
estimatedColumnWidths[_PickerColumnType.year.index]!,
estimatedColumnWidths[_PickerColumnType.month.index]!,
estimatedColumnWidths[_PickerColumnType.dayOfMonth.index]!,
];
break;
case DatePickerDateOrder.ydm:
pickerBuilders = <_ColumnBuilder>[_buildYearPicker, _buildDayPicker, _buildMonthPicker];
columnWidths = <double>[
estimatedColumnWidths[_PickerColumnType.year.index],
estimatedColumnWidths[_PickerColumnType.dayOfMonth.index],
estimatedColumnWidths[_PickerColumnType.month.index]];
estimatedColumnWidths[_PickerColumnType.year.index]!,
estimatedColumnWidths[_PickerColumnType.dayOfMonth.index]!,
estimatedColumnWidths[_PickerColumnType.month.index]!,
];
break;
default:
assert(false, 'date order is not specified');
@ -1358,7 +1357,7 @@ class _CupertinoDatePickerDateState extends State<CupertinoDatePicker> {
id: i,
child: pickerBuilders[i](
offAxisFraction,
(BuildContext context, Widget child) {
(BuildContext context, Widget? child) {
return Container(
alignment: i == columnWidths.length - 1
? alignCenterLeft
@ -1376,7 +1375,7 @@ class _CupertinoDatePickerDateState extends State<CupertinoDatePicker> {
}
return MediaQuery(
data: MediaQuery.of(context).copyWith(textScaleFactor: 1.0),
data: MediaQuery.of(context)!.copyWith(textScaleFactor: 1.0),
child: DefaultTextStyle.merge(
style: _kDefaultPickerTextStyle,
child: CustomMultiChildLayout(
@ -1464,14 +1463,14 @@ class CupertinoTimerPicker extends StatefulWidget {
/// [secondInterval] is the granularity of the second spinner. Must be a
/// positive integer factor of 60.
CupertinoTimerPicker({
Key key,
Key? key,
this.mode = CupertinoTimerPickerMode.hms,
this.initialTimerDuration = Duration.zero,
this.minuteInterval = 1,
this.secondInterval = 1,
this.alignment = Alignment.center,
this.backgroundColor,
@required this.onTimerDurationChanged,
required this.onTimerDurationChanged,
}) : assert(mode != null),
assert(onTimerDurationChanged != null),
assert(initialTimerDuration >= Duration.zero),
@ -1508,15 +1507,15 @@ class CupertinoTimerPicker extends StatefulWidget {
/// Background color of timer picker.
///
/// Defaults to null, which disables background painting entirely.
final Color backgroundColor;
final Color? backgroundColor;
@override
State<StatefulWidget> createState() => _CupertinoTimerPickerState();
}
class _CupertinoTimerPickerState extends State<CupertinoTimerPicker> {
TextDirection textDirection;
CupertinoLocalizations localizations;
late TextDirection textDirection;
late CupertinoLocalizations localizations;
int get textDirectionFactor {
switch (textDirection) {
case TextDirection.ltr:
@ -1524,25 +1523,24 @@ class _CupertinoTimerPickerState extends State<CupertinoTimerPicker> {
case TextDirection.rtl:
return -1;
}
return 1;
}
// The currently selected values of the picker.
int selectedHour;
int selectedMinute;
int selectedSecond;
int? selectedHour;
late int selectedMinute;
int? selectedSecond;
// On iOS the selected values won't be reported until the scrolling fully stops.
// The values below are the latest selected values when the picker comes to a full stop.
int lastSelectedHour;
int lastSelectedMinute;
int lastSelectedSecond;
int? lastSelectedHour;
int? lastSelectedMinute;
int? lastSelectedSecond;
final TextPainter textPainter = TextPainter();
final List<String> numbers = List<String>.generate(10, (int i) => '${9 - i}');
double numberLabelWidth;
double numberLabelHeight;
double numberLabelBaseline;
late double numberLabelWidth;
late double numberLabelHeight;
late double numberLabelBaseline;
@override
void initState() {
@ -1556,7 +1554,7 @@ class _CupertinoTimerPickerState extends State<CupertinoTimerPicker> {
if (widget.mode != CupertinoTimerPickerMode.hm)
selectedSecond = widget.initialTimerDuration.inSeconds % 60;
PaintingBinding.instance.systemFonts.addListener(_handleSystemFontsChange);
PaintingBinding.instance!.systemFonts.addListener(_handleSystemFontsChange);
}
void _handleSystemFontsChange() {
@ -1569,7 +1567,7 @@ class _CupertinoTimerPickerState extends State<CupertinoTimerPicker> {
@override
void dispose() {
PaintingBinding.instance.systemFonts.removeListener(_handleSystemFontsChange);
PaintingBinding.instance!.systemFonts.removeListener(_handleSystemFontsChange);
super.dispose();
}
@ -1587,8 +1585,8 @@ class _CupertinoTimerPickerState extends State<CupertinoTimerPicker> {
void didChangeDependencies() {
super.didChangeDependencies();
textDirection = Directionality.of(context);
localizations = CupertinoLocalizations.of(context);
textDirection = Directionality.of(context)!;
localizations = CupertinoLocalizations.of(context)!;
_measureLabelMetrics();
}
@ -1598,7 +1596,7 @@ class _CupertinoTimerPickerState extends State<CupertinoTimerPicker> {
final TextStyle textStyle = _textStyleFrom(context);
double maxWidth = double.negativeInfinity;
String widestNumber;
String? widestNumber;
// Assumes that:
// - 2-digit numbers are always wider than 1-digit numbers.
@ -1683,7 +1681,7 @@ class _CupertinoTimerPickerState extends State<CupertinoTimerPicker> {
Widget _buildHourPicker(EdgeInsetsDirectional additionalPadding) {
return CupertinoPicker(
scrollController: FixedExtentScrollController(initialItem: selectedHour),
scrollController: FixedExtentScrollController(initialItem: selectedHour!),
offAxisFraction: -0.5 * textDirectionFactor,
itemExtent: _kItemExtent,
backgroundColor: widget.backgroundColor,
@ -1693,7 +1691,7 @@ class _CupertinoTimerPickerState extends State<CupertinoTimerPicker> {
selectedHour = index;
widget.onTimerDurationChanged(
Duration(
hours: selectedHour,
hours: selectedHour!,
minutes: selectedMinute,
seconds: selectedSecond ?? 0));
});
@ -1723,7 +1721,7 @@ class _CupertinoTimerPickerState extends State<CupertinoTimerPicker> {
child: _buildHourPicker(additionalPadding),
),
_buildLabel(
localizations.timerPickerHourLabel(lastSelectedHour ?? selectedHour),
localizations.timerPickerHourLabel(lastSelectedHour ?? selectedHour!),
additionalPadding,
),
],
@ -1801,7 +1799,7 @@ class _CupertinoTimerPickerState extends State<CupertinoTimerPicker> {
return CupertinoPicker(
scrollController: FixedExtentScrollController(
initialItem: selectedSecond ~/ widget.secondInterval,
initialItem: selectedSecond! ~/ widget.secondInterval,
),
offAxisFraction: offAxisFraction,
itemExtent: _kItemExtent,
@ -1815,7 +1813,7 @@ class _CupertinoTimerPickerState extends State<CupertinoTimerPicker> {
Duration(
hours: selectedHour ?? 0,
minutes: selectedMinute,
seconds: selectedSecond));
seconds: selectedSecond!));
});
},
children: List<Widget>.generate(60 ~/ widget.secondInterval, (int index) {
@ -1845,7 +1843,7 @@ class _CupertinoTimerPickerState extends State<CupertinoTimerPicker> {
child: _buildSecondPicker(additionalPadding),
),
_buildLabel(
localizations.timerPickerSecondLabel(lastSelectedSecond ?? selectedSecond),
localizations.timerPickerSecondLabel(lastSelectedSecond ?? selectedSecond!),
additionalPadding,
),
],
@ -1902,7 +1900,7 @@ class _CupertinoTimerPickerState extends State<CupertinoTimerPicker> {
return MediaQuery(
// The native iOS picker's text scaling is fixed, so we will also fix it
// as well in our picker.
data: MediaQuery.of(context).copyWith(textScaleFactor: 1.0),
data: MediaQuery.of(context)!.copyWith(textScaleFactor: 1.0),
child: CupertinoTheme(
data: themeData.copyWith(
textTheme: themeData.textTheme.copyWith(

View file

@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:math' as math;
import 'dart:ui' show ImageFilter;
@ -97,7 +95,7 @@ const double _kMaxRegularTextScaleFactor = 1.4;
// Accessibility mode on iOS is determined by the text scale factor that the
// user has selected.
bool _isInAccessibilityMode(BuildContext context) {
final MediaQueryData data = MediaQuery.of(context, nullOk: true);
final MediaQueryData? data = MediaQuery.of(context, nullOk: true);
return data != null && data.textScaleFactor > _kMaxRegularTextScaleFactor;
}
@ -131,7 +129,7 @@ class CupertinoAlertDialog extends StatelessWidget {
///
/// The [actions] must not be null.
const CupertinoAlertDialog({
Key key,
Key? key,
this.title,
this.content,
this.actions = const <Widget>[],
@ -146,13 +144,13 @@ class CupertinoAlertDialog extends StatelessWidget {
/// of the dialog.
///
/// Typically a [Text] widget.
final Widget title;
final Widget? title;
/// The (optional) content of the dialog is displayed in the center of the
/// dialog in a lighter font.
///
/// Typically a [Text] widget.
final Widget content;
final Widget? content;
/// The (optional) set of actions that are displayed at the bottom of the
/// dialog.
@ -170,7 +168,7 @@ class CupertinoAlertDialog extends StatelessWidget {
///
/// * [actionScrollController], which can be used for controlling the actions
/// section when there are many actions.
final ScrollController scrollController;
final ScrollController? scrollController;
/// A scroll controller that can be used to control the scrolling of the
/// actions in the dialog.
@ -181,7 +179,7 @@ class CupertinoAlertDialog extends StatelessWidget {
///
/// * [scrollController], which can be used for controlling the [content]
/// section when it is long.
final ScrollController actionScrollController;
final ScrollController? actionScrollController;
/// {@macro flutter.material.dialog.insetAnimationDuration}
final Duration insetAnimationDuration;
@ -228,20 +226,20 @@ class CupertinoAlertDialog extends StatelessWidget {
@override
Widget build(BuildContext context) {
final CupertinoLocalizations localizations = CupertinoLocalizations.of(context);
final CupertinoLocalizations localizations = CupertinoLocalizations.of(context)!;
final bool isInAccessibilityMode = _isInAccessibilityMode(context);
final double textScaleFactor = MediaQuery.of(context).textScaleFactor;
final double textScaleFactor = MediaQuery.of(context)!.textScaleFactor;
return CupertinoUserInterfaceLevel(
data: CupertinoUserInterfaceLevelData.elevated,
child: MediaQuery(
data: MediaQuery.of(context).copyWith(
data: MediaQuery.of(context)!.copyWith(
// iOS does not shrink dialog content below a 1.0 scale factor
textScaleFactor: math.max(textScaleFactor, 1.0),
),
child: LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
return AnimatedPadding(
padding: MediaQuery.of(context).viewInsets +
padding: MediaQuery.of(context)!.viewInsets +
const EdgeInsets.symmetric(horizontal: 40.0, vertical: 24.0),
duration: insetAnimationDuration,
curve: insetAnimationCurve,
@ -302,12 +300,12 @@ class CupertinoAlertDialog extends StatelessWidget {
class CupertinoDialog extends StatelessWidget {
/// Creates an iOS-style dialog.
const CupertinoDialog({
Key key,
Key? key,
this.child,
}) : super(key: key);
/// The widget below this widget in the tree.
final Widget child;
final Widget? child;
@override
Widget build(BuildContext context) {
@ -340,7 +338,7 @@ class CupertinoDialog extends StatelessWidget {
class CupertinoPopupSurface extends StatelessWidget {
/// Creates an iOS-style rounded rectangle popup surface.
const CupertinoPopupSurface({
Key key,
Key? key,
this.isSurfacePainted = true,
this.child,
}) : super(key: key);
@ -356,7 +354,7 @@ class CupertinoPopupSurface extends StatelessWidget {
final bool isSurfacePainted;
/// The widget below this widget in the tree.
final Widget child;
final Widget? child;
@override
Widget build(BuildContext context) {
@ -379,9 +377,9 @@ class CupertinoPopupSurface extends StatelessWidget {
// See [_RenderCupertinoDialog] for specific layout policy details.
class _CupertinoDialogRenderWidget extends RenderObjectWidget {
const _CupertinoDialogRenderWidget({
Key key,
@required this.contentSection,
@required this.actionsSection,
Key? key,
required this.contentSection,
required this.actionsSection,
}) : super(key: key);
final Widget contentSection;
@ -390,9 +388,9 @@ class _CupertinoDialogRenderWidget extends RenderObjectWidget {
@override
RenderObject createRenderObject(BuildContext context) {
return _RenderCupertinoDialog(
dividerThickness: _kDividerThickness / MediaQuery.of(context).devicePixelRatio,
dividerThickness: _kDividerThickness / MediaQuery.of(context)!.devicePixelRatio,
isInAccessibilityMode: _isInAccessibilityMode(context),
dividerColor: CupertinoDynamicColor.resolve(CupertinoColors.separator, context),
dividerColor: CupertinoDynamicColor.resolve(CupertinoColors.separator, context)!,
);
}
@ -400,7 +398,7 @@ class _CupertinoDialogRenderWidget extends RenderObjectWidget {
void updateRenderObject(BuildContext context, _RenderCupertinoDialog renderObject) {
renderObject
..isInAccessibilityMode = _isInAccessibilityMode(context)
..dividerColor = CupertinoDynamicColor.resolve(CupertinoColors.separator, context);
..dividerColor = CupertinoDynamicColor.resolve(CupertinoColors.separator, context)!;
}
@override
@ -412,8 +410,8 @@ class _CupertinoDialogRenderWidget extends RenderObjectWidget {
class _CupertinoDialogRenderElement extends RenderObjectElement {
_CupertinoDialogRenderElement(_CupertinoDialogRenderWidget widget) : super(widget);
Element _contentElement;
Element _actionsElement;
Element? _contentElement;
Element? _actionsElement;
@override
_CupertinoDialogRenderWidget get widget => super.widget as _CupertinoDialogRenderWidget;
@ -424,15 +422,15 @@ class _CupertinoDialogRenderElement extends RenderObjectElement {
@override
void visitChildren(ElementVisitor visitor) {
if (_contentElement != null) {
visitor(_contentElement);
visitor(_contentElement!);
}
if (_actionsElement != null) {
visitor(_actionsElement);
visitor(_actionsElement!);
}
}
@override
void mount(Element parent, dynamic newSlot) {
void mount(Element? parent, dynamic newSlot) {
super.mount(parent, newSlot);
_contentElement = updateChild(_contentElement, widget.contentSection, _AlertDialogSections.contentSection);
_actionsElement = updateChild(_actionsElement, widget.actionsSection, _AlertDialogSections.actionsSection);
@ -513,11 +511,11 @@ class _CupertinoDialogRenderElement extends RenderObjectElement {
// section is given whatever height remains.
class _RenderCupertinoDialog extends RenderBox {
_RenderCupertinoDialog({
RenderBox contentSection,
RenderBox actionsSection,
RenderBox? contentSection,
RenderBox? actionsSection,
double dividerThickness = 0.0,
bool isInAccessibilityMode = false,
Color dividerColor,
required Color dividerColor,
}) : _contentSection = contentSection,
_actionsSection = actionsSection,
_dividerThickness = dividerThickness,
@ -527,30 +525,30 @@ class _RenderCupertinoDialog extends RenderBox {
..style = PaintingStyle.fill;
RenderBox get contentSection => _contentSection;
RenderBox _contentSection;
set contentSection(RenderBox newContentSection) {
RenderBox? get contentSection => _contentSection;
RenderBox? _contentSection;
set contentSection(RenderBox? newContentSection) {
if (newContentSection != _contentSection) {
if (_contentSection != null) {
dropChild(_contentSection);
dropChild(_contentSection!);
}
_contentSection = newContentSection;
if (_contentSection != null) {
adoptChild(_contentSection);
adoptChild(_contentSection!);
}
}
}
RenderBox get actionsSection => _actionsSection;
RenderBox _actionsSection;
set actionsSection(RenderBox newActionsSection) {
RenderBox? get actionsSection => _actionsSection;
RenderBox? _actionsSection;
set actionsSection(RenderBox? newActionsSection) {
if (newActionsSection != _actionsSection) {
if (null != _actionsSection) {
dropChild(_actionsSection);
dropChild(_actionsSection!);
}
_actionsSection = newActionsSection;
if (null != _actionsSection) {
adoptChild(_actionsSection);
adoptChild(_actionsSection!);
}
}
}
@ -585,10 +583,10 @@ class _RenderCupertinoDialog extends RenderBox {
void attach(PipelineOwner owner) {
super.attach(owner);
if (null != contentSection) {
contentSection.attach(owner);
contentSection!.attach(owner);
}
if (null != actionsSection) {
actionsSection.attach(owner);
actionsSection!.attach(owner);
}
}
@ -596,20 +594,20 @@ class _RenderCupertinoDialog extends RenderBox {
void detach() {
super.detach();
if (null != contentSection) {
contentSection.detach();
contentSection!.detach();
}
if (null != actionsSection) {
actionsSection.detach();
actionsSection!.detach();
}
}
@override
void redepthChildren() {
if (null != contentSection) {
redepthChild(contentSection);
redepthChild(contentSection!);
}
if (null != actionsSection) {
redepthChild(actionsSection);
redepthChild(actionsSection!);
}
}
@ -623,17 +621,17 @@ class _RenderCupertinoDialog extends RenderBox {
@override
void visitChildren(RenderObjectVisitor visitor) {
if (contentSection != null) {
visitor(contentSection);
visitor(contentSection!);
}
if (actionsSection != null) {
visitor(actionsSection);
visitor(actionsSection!);
}
}
@override
List<DiagnosticsNode> debugDescribeChildren() => <DiagnosticsNode>[
if (contentSection != null) contentSection.toDiagnosticsNode(name: 'content'),
if (actionsSection != null) actionsSection.toDiagnosticsNode(name: 'actions'),
if (contentSection != null) contentSection!.toDiagnosticsNode(name: 'content'),
if (actionsSection != null) actionsSection!.toDiagnosticsNode(name: 'actions'),
];
@override
@ -648,8 +646,8 @@ class _RenderCupertinoDialog extends RenderBox {
@override
double computeMinIntrinsicHeight(double width) {
final double contentHeight = contentSection.getMinIntrinsicHeight(width);
final double actionsHeight = actionsSection.getMinIntrinsicHeight(width);
final double contentHeight = contentSection!.getMinIntrinsicHeight(width);
final double actionsHeight = actionsSection!.getMinIntrinsicHeight(width);
final bool hasDivider = contentHeight > 0.0 && actionsHeight > 0.0;
final double height = contentHeight + (hasDivider ? _dividerThickness : 0.0) + actionsHeight;
@ -660,8 +658,8 @@ class _RenderCupertinoDialog extends RenderBox {
@override
double computeMaxIntrinsicHeight(double width) {
final double contentHeight = contentSection.getMaxIntrinsicHeight(width);
final double actionsHeight = actionsSection.getMaxIntrinsicHeight(width);
final double contentHeight = contentSection!.getMaxIntrinsicHeight(width);
final double actionsHeight = actionsSection!.getMaxIntrinsicHeight(width);
final bool hasDivider = contentHeight > 0.0 && actionsHeight > 0.0;
final double height = contentHeight + (hasDivider ? _dividerThickness : 0.0) + actionsHeight;
@ -685,25 +683,25 @@ class _RenderCupertinoDialog extends RenderBox {
}
void performRegularLayout() {
final bool hasDivider = contentSection.getMaxIntrinsicHeight(_dialogWidth) > 0.0
&& actionsSection.getMaxIntrinsicHeight(_dialogWidth) > 0.0;
final bool hasDivider = contentSection!.getMaxIntrinsicHeight(_dialogWidth) > 0.0
&& actionsSection!.getMaxIntrinsicHeight(_dialogWidth) > 0.0;
final double dividerThickness = hasDivider ? _dividerThickness : 0.0;
final double minActionsHeight = actionsSection.getMinIntrinsicHeight(_dialogWidth);
final double minActionsHeight = actionsSection!.getMinIntrinsicHeight(_dialogWidth);
// Size alert dialog content.
contentSection.layout(
contentSection!.layout(
constraints.deflate(EdgeInsets.only(bottom: minActionsHeight + dividerThickness)),
parentUsesSize: true,
);
final Size contentSize = contentSection.size;
final Size contentSize = contentSection!.size;
// Size alert dialog actions.
actionsSection.layout(
actionsSection!.layout(
constraints.deflate(EdgeInsets.only(top: contentSize.height + dividerThickness)),
parentUsesSize: true,
);
final Size actionsSize = actionsSection.size;
final Size actionsSize = actionsSection!.size;
// Calculate overall dialog height.
final double dialogHeight = contentSize.height + dividerThickness + actionsSize.height;
@ -715,18 +713,18 @@ class _RenderCupertinoDialog extends RenderBox {
// Set the position of the actions box to sit at the bottom of the dialog.
// The content box defaults to the top left, which is where we want it.
assert(actionsSection.parentData is BoxParentData);
final BoxParentData actionParentData = actionsSection.parentData as BoxParentData;
assert(actionsSection!.parentData is BoxParentData);
final BoxParentData actionParentData = actionsSection!.parentData as BoxParentData;
actionParentData.offset = Offset(0.0, contentSize.height + dividerThickness);
}
void performAccessibilityLayout() {
final bool hasDivider = contentSection.getMaxIntrinsicHeight(_dialogWidth) > 0.0
&& actionsSection.getMaxIntrinsicHeight(_dialogWidth) > 0.0;
final bool hasDivider = contentSection!.getMaxIntrinsicHeight(_dialogWidth) > 0.0
&& actionsSection!.getMaxIntrinsicHeight(_dialogWidth) > 0.0;
final double dividerThickness = hasDivider ? _dividerThickness : 0.0;
final double maxContentHeight = contentSection.getMaxIntrinsicHeight(_dialogWidth);
final double maxActionsHeight = actionsSection.getMaxIntrinsicHeight(_dialogWidth);
final double maxContentHeight = contentSection!.getMaxIntrinsicHeight(_dialogWidth);
final double maxActionsHeight = actionsSection!.getMaxIntrinsicHeight(_dialogWidth);
Size contentSize;
Size actionsSize;
@ -737,34 +735,34 @@ class _RenderCupertinoDialog extends RenderBox {
// section.
// Size alert dialog actions.
actionsSection.layout(
actionsSection!.layout(
constraints.deflate(EdgeInsets.only(top: constraints.maxHeight / 2.0)),
parentUsesSize: true,
);
actionsSize = actionsSection.size;
actionsSize = actionsSection!.size;
// Size alert dialog content.
contentSection.layout(
contentSection!.layout(
constraints.deflate(EdgeInsets.only(bottom: actionsSize.height + dividerThickness)),
parentUsesSize: true,
);
contentSize = contentSection.size;
contentSize = contentSection!.size;
} else {
// Everything fits. Give content and actions all the space they want.
// Size alert dialog content.
contentSection.layout(
contentSection!.layout(
constraints,
parentUsesSize: true,
);
contentSize = contentSection.size;
contentSize = contentSection!.size;
// Size alert dialog actions.
actionsSection.layout(
actionsSection!.layout(
constraints.deflate(EdgeInsets.only(top: contentSize.height)),
parentUsesSize: true,
);
actionsSize = actionsSection.size;
actionsSize = actionsSection!.size;
}
// Calculate overall dialog height.
@ -777,30 +775,30 @@ class _RenderCupertinoDialog extends RenderBox {
// Set the position of the actions box to sit at the bottom of the dialog.
// The content box defaults to the top left, which is where we want it.
assert(actionsSection.parentData is BoxParentData);
final BoxParentData actionParentData = actionsSection.parentData as BoxParentData;
assert(actionsSection!.parentData is BoxParentData);
final BoxParentData actionParentData = actionsSection!.parentData as BoxParentData;
actionParentData.offset = Offset(0.0, contentSize.height + dividerThickness);
}
@override
void paint(PaintingContext context, Offset offset) {
final BoxParentData contentParentData = contentSection.parentData as BoxParentData;
contentSection.paint(context, offset + contentParentData.offset);
final BoxParentData contentParentData = contentSection!.parentData as BoxParentData;
contentSection!.paint(context, offset + contentParentData.offset);
final bool hasDivider = contentSection.size.height > 0.0 && actionsSection.size.height > 0.0;
final bool hasDivider = contentSection!.size.height > 0.0 && actionsSection!.size.height > 0.0;
if (hasDivider) {
_paintDividerBetweenContentAndActions(context.canvas, offset);
}
final BoxParentData actionsParentData = actionsSection.parentData as BoxParentData;
actionsSection.paint(context, offset + actionsParentData.offset);
final BoxParentData actionsParentData = actionsSection!.parentData as BoxParentData;
actionsSection!.paint(context, offset + actionsParentData.offset);
}
void _paintDividerBetweenContentAndActions(Canvas canvas, Offset offset) {
canvas.drawRect(
Rect.fromLTWH(
offset.dx,
offset.dy + contentSection.size.height,
offset.dy + contentSection!.size.height,
size.width,
_dividerThickness,
),
@ -809,15 +807,15 @@ class _RenderCupertinoDialog extends RenderBox {
}
@override
bool hitTestChildren(BoxHitTestResult result, { Offset position }) {
final BoxParentData contentSectionParentData = contentSection.parentData as BoxParentData;
final BoxParentData actionsSectionParentData = actionsSection.parentData as BoxParentData;
bool hitTestChildren(BoxHitTestResult result, { required Offset position }) {
final BoxParentData contentSectionParentData = contentSection!.parentData as BoxParentData;
final BoxParentData actionsSectionParentData = actionsSection!.parentData as BoxParentData;
return result.addWithPaintOffset(
offset: contentSectionParentData.offset,
position: position,
hitTest: (BoxHitTestResult result, Offset transformed) {
assert(transformed == position - contentSectionParentData.offset);
return contentSection.hitTest(result, position: transformed);
return contentSection!.hitTest(result, position: transformed);
},
)
|| result.addWithPaintOffset(
@ -825,7 +823,7 @@ class _RenderCupertinoDialog extends RenderBox {
position: position,
hitTest: (BoxHitTestResult result, Offset transformed) {
assert(transformed == position - actionsSectionParentData.offset);
return actionsSection.hitTest(result, position: transformed);
return actionsSection!.hitTest(result, position: transformed);
},
);
}
@ -845,7 +843,7 @@ enum _AlertDialogSections {
// a SingleChildScrollView with a zero-sized Container.
class _CupertinoAlertContentSection extends StatelessWidget {
const _CupertinoAlertContentSection({
Key key,
Key? key,
this.title,
this.content,
this.scrollController,
@ -855,20 +853,20 @@ class _CupertinoAlertContentSection extends StatelessWidget {
// of the dialog.
//
// Typically a Text widget.
final Widget title;
final Widget? title;
// The (optional) content of the dialog is displayed in the center of the
// dialog in a lighter font.
//
// Typically a Text widget.
final Widget content;
final Widget? content;
// A scroll controller that can be used to control the scrolling of the
// content in the dialog.
//
// Defaults to null, and is typically not needed, since most alert contents
// are short.
final ScrollController scrollController;
final ScrollController? scrollController;
@override
Widget build(BuildContext context) {
@ -879,7 +877,7 @@ class _CupertinoAlertContentSection extends StatelessWidget {
);
}
final double textScaleFactor = MediaQuery.of(context).textScaleFactor;
final double textScaleFactor = MediaQuery.of(context)!.textScaleFactor;
final List<Widget> titleContentGroup = <Widget>[
if (title != null)
Padding(
@ -894,7 +892,7 @@ class _CupertinoAlertContentSection extends StatelessWidget {
color: CupertinoDynamicColor.resolve(CupertinoColors.label, context),
),
textAlign: TextAlign.center,
child: title,
child: title!,
),
),
if (content != null)
@ -910,7 +908,7 @@ class _CupertinoAlertContentSection extends StatelessWidget {
color: CupertinoDynamicColor.resolve(CupertinoColors.label, context),
),
textAlign: TextAlign.center,
child: content,
child: content!,
),
),
];
@ -934,8 +932,8 @@ class _CupertinoAlertContentSection extends StatelessWidget {
// and layout.
class _CupertinoAlertActionSection extends StatefulWidget {
const _CupertinoAlertActionSection({
Key key,
@required this.children,
Key? key,
required this.children,
this.scrollController,
}) : assert(children != null),
super(key: key);
@ -947,7 +945,7 @@ class _CupertinoAlertActionSection extends StatefulWidget {
//
// Defaults to null, and is typically not needed, since most alert dialogs
// don't have many actions.
final ScrollController scrollController;
final ScrollController? scrollController;
@override
_CupertinoAlertActionSectionState createState() => _CupertinoAlertActionSectionState();
@ -956,7 +954,7 @@ class _CupertinoAlertActionSection extends StatefulWidget {
class _CupertinoAlertActionSectionState extends State<_CupertinoAlertActionSection> {
@override
Widget build(BuildContext context) {
final double devicePixelRatio = MediaQuery.of(context).devicePixelRatio;
final double devicePixelRatio = MediaQuery.of(context)!.devicePixelRatio;
final List<Widget> interactiveButtons = <Widget>[];
for (int i = 0; i < widget.children.length; i += 1) {
@ -986,7 +984,7 @@ class _CupertinoAlertActionSectionState extends State<_CupertinoAlertActionSecti
// appropriately by _RenderCupertinoDialogActions.
class _PressableActionButton extends StatefulWidget {
const _PressableActionButton({
@required this.child,
required this.child,
});
final Widget child;
@ -1033,9 +1031,9 @@ class _PressableActionButtonState extends State<_PressableActionButton> {
// incoming [isPressed] property.
class _ActionButtonParentDataWidget extends ParentDataWidget<_ActionButtonParentData> {
const _ActionButtonParentDataWidget({
Key key,
this.isPressed,
@required Widget child,
Key? key,
required this.isPressed,
required Widget child,
}) : super(key: key, child: child);
final bool isPressed;
@ -1048,7 +1046,7 @@ class _ActionButtonParentDataWidget extends ParentDataWidget<_ActionButtonParent
parentData.isPressed = isPressed;
// Force a repaint.
final AbstractNode targetParent = renderObject.parent;
final AbstractNode? targetParent = renderObject.parent;
if (targetParent is RenderObject)
targetParent.markNeedsPaint();
}
@ -1077,12 +1075,12 @@ class _ActionButtonParentData extends MultiChildLayoutParentData {
class CupertinoDialogAction extends StatelessWidget {
/// Creates an action for an iOS-style dialog.
const CupertinoDialogAction({
Key key,
Key? key,
this.onPressed,
this.isDefaultAction = false,
this.isDestructiveAction = false,
this.textStyle,
@required this.child,
required this.child,
}) : assert(child != null),
assert(isDefaultAction != null),
assert(isDestructiveAction != null),
@ -1092,7 +1090,7 @@ class CupertinoDialogAction extends StatelessWidget {
/// activated.
///
/// If this is set to null, the button will be disabled.
final VoidCallback onPressed;
final VoidCallback? onPressed;
/// Set to true if button is the default choice in the dialog.
///
@ -1117,7 +1115,7 @@ class CupertinoDialogAction extends StatelessWidget {
/// ensure that this resizing policy always works as expected, [textStyle]
/// must be used if a text size is desired other than that specified in
/// [_kCupertinoDialogActionStyle].
final TextStyle textStyle;
final TextStyle? textStyle;
/// The widget below this widget in the tree.
///
@ -1138,9 +1136,9 @@ class CupertinoDialogAction extends StatelessWidget {
//
// This policy only applies when the device is not in accessibility mode.
Widget _buildContentWithRegularSizingPolicy({
@required BuildContext context,
@required TextStyle textStyle,
@required Widget content,
required BuildContext context,
required TextStyle textStyle,
required Widget content,
}) {
final bool isInAccessibilityMode = _isInAccessibilityMode(context);
final double dialogWidth = isInAccessibilityMode
@ -1151,7 +1149,7 @@ class CupertinoDialogAction extends StatelessWidget {
// iOS scale factor) vs the minimum text size that we allow in action
// buttons. This ratio information is used to automatically scale down action
// button text to fit the available space.
final double fontSizeRatio = (textScaleFactor * textStyle.fontSize) / _kMinButtonFontSize;
final double fontSizeRatio = (textScaleFactor * textStyle.fontSize!) / _kMinButtonFontSize;
final double padding = _calculatePadding(context);
return IntrinsicHeight(
@ -1184,8 +1182,8 @@ class CupertinoDialogAction extends StatelessWidget {
// accessibility mode. If text is used as the content, the text wraps instead
// of ellipsizing.
Widget _buildContentWithAccessibilitySizingPolicy({
@required TextStyle textStyle,
@required Widget content,
required TextStyle textStyle,
required Widget content,
}) {
return DefaultTextStyle(
style: textStyle,
@ -1209,7 +1207,7 @@ class CupertinoDialogAction extends StatelessWidget {
}
if (!enabled) {
style = style.copyWith(color: style.color.withOpacity(0.5));
style = style.copyWith(color: style.color!.withOpacity(0.5));
}
// Apply a sizing policy to the action button's content based on whether or
@ -1256,8 +1254,8 @@ class CupertinoDialogAction extends StatelessWidget {
// See [_RenderCupertinoDialogActions] for specific layout policy details.
class _CupertinoDialogActionsRenderWidget extends MultiChildRenderObjectWidget {
_CupertinoDialogActionsRenderWidget({
Key key,
@required List<Widget> actionButtons,
Key? key,
required List<Widget> actionButtons,
double dividerThickness = 0.0,
}) : _dividerThickness = dividerThickness,
super(key: key, children: actionButtons);
@ -1271,9 +1269,9 @@ class _CupertinoDialogActionsRenderWidget extends MultiChildRenderObjectWidget {
? _kAccessibilityCupertinoDialogWidth
: _kCupertinoDialogWidth,
dividerThickness: _dividerThickness,
dialogColor: CupertinoDynamicColor.resolve(_kDialogColor, context),
dialogPressedColor: CupertinoDynamicColor.resolve(_kDialogPressedColor, context),
dividerColor: CupertinoDynamicColor.resolve(CupertinoColors.separator, context),
dialogColor: CupertinoDynamicColor.resolve(_kDialogColor, context)!,
dialogPressedColor: CupertinoDynamicColor.resolve(_kDialogPressedColor, context)!,
dividerColor: CupertinoDynamicColor.resolve(CupertinoColors.separator, context)!,
);
}
@ -1284,9 +1282,9 @@ class _CupertinoDialogActionsRenderWidget extends MultiChildRenderObjectWidget {
? _kAccessibilityCupertinoDialogWidth
: _kCupertinoDialogWidth
..dividerThickness = _dividerThickness
..dialogColor = CupertinoDynamicColor.resolve(_kDialogColor, context)
..dialogPressedColor = CupertinoDynamicColor.resolve(_kDialogPressedColor, context)
..dividerColor = CupertinoDynamicColor.resolve(CupertinoColors.separator, context);
..dialogColor = CupertinoDynamicColor.resolve(_kDialogColor, context)!
..dialogPressedColor = CupertinoDynamicColor.resolve(_kDialogPressedColor, context)!
..dividerColor = CupertinoDynamicColor.resolve(CupertinoColors.separator, context)!;
}
}
@ -1328,12 +1326,12 @@ class _RenderCupertinoDialogActions extends RenderBox
with ContainerRenderObjectMixin<RenderBox, MultiChildLayoutParentData>,
RenderBoxContainerDefaultsMixin<RenderBox, MultiChildLayoutParentData> {
_RenderCupertinoDialogActions({
List<RenderBox> children,
@required double dialogWidth,
List<RenderBox>? children,
required double dialogWidth,
double dividerThickness = 0.0,
@required Color dialogColor,
@required Color dialogPressedColor,
@required Color dividerColor,
required Color dialogColor,
required Color dialogPressedColor,
required Color dividerColor,
}) : _dialogWidth = dialogWidth,
_buttonBackgroundPaint = Paint()
..color = dialogColor
@ -1395,7 +1393,7 @@ class _RenderCupertinoDialogActions extends RenderBox
}
Iterable<RenderBox> get _pressedButtons sync* {
RenderBox currentChild = firstChild;
RenderBox? currentChild = firstChild;
while (currentChild != null) {
assert(currentChild.parentData is _ActionButtonParentData);
final _ActionButtonParentData parentData = currentChild.parentData as _ActionButtonParentData;
@ -1407,7 +1405,7 @@ class _RenderCupertinoDialogActions extends RenderBox
}
bool get _isButtonPressed {
RenderBox currentChild = firstChild;
RenderBox? currentChild = firstChild;
while (currentChild != null) {
assert(currentChild.parentData is _ActionButtonParentData);
final _ActionButtonParentData parentData = currentChild.parentData as _ActionButtonParentData;
@ -1463,12 +1461,12 @@ class _RenderCupertinoDialogActions extends RenderBox
double minHeight;
if (childCount == 1) {
minHeight = firstChild.getMinIntrinsicHeight(width);
minHeight = firstChild!.getMinIntrinsicHeight(width);
} else {
final double perButtonWidth = (width - dividerThickness) / 2.0;
minHeight = math.max(
firstChild.getMinIntrinsicHeight(perButtonWidth),
lastChild.getMinIntrinsicHeight(perButtonWidth),
firstChild!.getMinIntrinsicHeight(perButtonWidth),
lastChild!.getMinIntrinsicHeight(perButtonWidth),
);
}
return minHeight;
@ -1479,9 +1477,9 @@ class _RenderCupertinoDialogActions extends RenderBox
double _computeMinIntrinsicHeightStacked(double width) {
assert(childCount >= 2);
return firstChild.getMinIntrinsicHeight(width)
return firstChild!.getMinIntrinsicHeight(width)
+ dividerThickness
+ (0.5 * childAfter(firstChild).getMinIntrinsicHeight(width));
+ (0.5 * childAfter(firstChild!)!.getMinIntrinsicHeight(width));
}
@override
@ -1492,7 +1490,7 @@ class _RenderCupertinoDialogActions extends RenderBox
maxHeight = 0.0;
} else if (childCount == 1) {
// One button. Our max intrinsic height is equal to the button's.
maxHeight = firstChild.getMaxIntrinsicHeight(width);
maxHeight = firstChild!.getMaxIntrinsicHeight(width);
} else if (childCount == 2) {
// Two buttons...
if (_isSingleButtonRow(width)) {
@ -1500,8 +1498,8 @@ class _RenderCupertinoDialogActions extends RenderBox
// to the taller of the 2 buttons.
final double perButtonWidth = (width - dividerThickness) / 2.0;
maxHeight = math.max(
firstChild.getMaxIntrinsicHeight(perButtonWidth),
lastChild.getMaxIntrinsicHeight(perButtonWidth),
firstChild!.getMaxIntrinsicHeight(perButtonWidth),
lastChild!.getMaxIntrinsicHeight(perButtonWidth),
);
} else {
// The 2 buttons do not fit side by side. Measure total height as a
@ -1523,7 +1521,7 @@ class _RenderCupertinoDialogActions extends RenderBox
final double allDividersHeight = (childCount - 1) * dividerThickness;
double heightAccumulation = allDividersHeight;
RenderBox button = firstChild;
RenderBox? button = firstChild;
while (button != null) {
heightAccumulation += button.getMaxIntrinsicHeight(width);
button = childAfter(button);
@ -1538,9 +1536,9 @@ class _RenderCupertinoDialogActions extends RenderBox
} else if (childCount == 2) {
// There are 2 buttons. If they can fit side-by-side then that's what
// we want to do. Otherwise, stack them vertically.
final double sideBySideWidth = firstChild.getMaxIntrinsicWidth(double.infinity)
final double sideBySideWidth = firstChild!.getMaxIntrinsicWidth(double.infinity)
+ dividerThickness
+ lastChild.getMaxIntrinsicWidth(double.infinity);
+ lastChild!.getMaxIntrinsicWidth(double.infinity);
isSingleButtonRow = sideBySideWidth <= width;
} else {
isSingleButtonRow = false;
@ -1555,13 +1553,13 @@ class _RenderCupertinoDialogActions extends RenderBox
if (childCount == 1) {
// We have 1 button. Our size is the width of the dialog and the height
// of the single button.
firstChild.layout(
firstChild!.layout(
constraints,
parentUsesSize: true,
);
size = constraints.constrain(
Size(dialogWidth, firstChild.size.height)
Size(dialogWidth, firstChild!.size.height)
);
} else {
// Each button gets half the available width, minus a single divider.
@ -1573,27 +1571,27 @@ class _RenderCupertinoDialogActions extends RenderBox
);
// Layout the 2 buttons.
firstChild.layout(
firstChild!.layout(
perButtonConstraints,
parentUsesSize: true,
);
lastChild.layout(
lastChild!.layout(
perButtonConstraints,
parentUsesSize: true,
);
// The 2nd button needs to be offset to the right.
assert(lastChild.parentData is MultiChildLayoutParentData);
final MultiChildLayoutParentData secondButtonParentData = lastChild.parentData as MultiChildLayoutParentData;
secondButtonParentData.offset = Offset(firstChild.size.width + dividerThickness, 0.0);
assert(lastChild!.parentData is MultiChildLayoutParentData);
final MultiChildLayoutParentData secondButtonParentData = lastChild!.parentData as MultiChildLayoutParentData;
secondButtonParentData.offset = Offset(firstChild!.size.width + dividerThickness, 0.0);
// Calculate our size based on the button sizes.
size = constraints.constrain(
Size(
dialogWidth,
math.max(
firstChild.size.height,
lastChild.size.height,
firstChild!.size.height,
lastChild!.size.height,
),
),
);
@ -1605,7 +1603,7 @@ class _RenderCupertinoDialogActions extends RenderBox
maxHeight: double.infinity,
);
RenderBox child = firstChild;
RenderBox? child = firstChild;
int index = 0;
double verticalOffset = 0.0;
while (child != null) {
@ -1654,12 +1652,12 @@ class _RenderCupertinoDialogActions extends RenderBox
// left or right button is pressed.
final Rect verticalDivider = childCount == 2 && !_isButtonPressed
? Rect.fromLTWH(
offset.dx + firstChild.size.width,
offset.dx + firstChild!.size.width,
offset.dy,
dividerThickness,
math.max(
firstChild.size.height,
lastChild.size.height,
firstChild!.size.height,
lastChild!.size.height,
),
)
: Rect.zero;
@ -1724,8 +1722,8 @@ class _RenderCupertinoDialogActions extends RenderBox
Offset accumulatingOffset = offset;
RenderBox child = firstChild;
RenderBox prevChild;
RenderBox? child = firstChild;
RenderBox? prevChild;
while (child != null) {
assert(child.parentData is _ActionButtonParentData);
final _ActionButtonParentData currentButtonParentData = child.parentData as _ActionButtonParentData;
@ -1782,7 +1780,7 @@ class _RenderCupertinoDialogActions extends RenderBox
}
void _drawButtons(PaintingContext context, Offset offset) {
RenderBox child = firstChild;
RenderBox? child = firstChild;
while (child != null) {
final MultiChildLayoutParentData childParentData = child.parentData as MultiChildLayoutParentData;
context.paintChild(child, childParentData.offset + offset);
@ -1791,7 +1789,7 @@ class _RenderCupertinoDialogActions extends RenderBox
}
@override
bool hitTestChildren(BoxHitTestResult result, { Offset position }) {
bool hitTestChildren(BoxHitTestResult result, { required Offset position }) {
return defaultHitTestChildren(result, position: position);
}
}

View file

@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
@ -156,7 +154,7 @@ abstract class CupertinoLocalizations {
/// there are, e.g. 'tab, 1 of 2' in United States English.
///
/// `tabIndex` and `tabCount` must be greater than or equal to one.
String tabSemanticsLabel({int tabIndex, int tabCount});
String tabSemanticsLabel({required int tabIndex, required int tabCount});
/// Hour that is shown in [CupertinoTimerPicker] corresponding to
/// the given hour value.
@ -241,7 +239,7 @@ abstract class CupertinoLocalizations {
/// ```dart
/// CupertinoLocalizations.of(context).anteMeridiemAbbreviation;
/// ```
static CupertinoLocalizations of(BuildContext context) {
static CupertinoLocalizations? of(BuildContext context) {
return Localizations.of<CupertinoLocalizations>(context, CupertinoLocalizations);
}
}
@ -364,7 +362,7 @@ class DefaultCupertinoLocalizations implements CupertinoLocalizations {
String get alertDialogLabel => 'Alert';
@override
String tabSemanticsLabel({int tabIndex, int tabCount}) {
String tabSemanticsLabel({required int tabIndex, required int tabCount}) {
assert(tabIndex >= 1);
assert(tabCount >= 1);
return 'Tab $tabIndex of $tabCount';

View file

@ -2,16 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:math';
import 'dart:ui' show lerpDouble, ImageFilter;
import 'package:flutter/animation.dart' show Curves;
import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter/animation.dart' show Curves;
import 'colors.dart';
import 'interface_level.dart';
@ -104,10 +102,9 @@ mixin CupertinoRouteTransitionMixin<T> on PageRoute<T> {
/// [CupertinoSliverNavigationBar]'s `middle`/`largeTitle` widgets when
/// one is not manually supplied.
/// {@endtemplate}
String get title;
String? get title;
ValueNotifier<String> _previousTitle;
ValueNotifier<String?>? _previousTitle;
/// The title string of the previous [CupertinoPageRoute].
///
@ -123,23 +120,23 @@ mixin CupertinoRouteTransitionMixin<T> on PageRoute<T> {
///
/// * [ValueListenableBuilder], which can be used to listen and rebuild
/// widgets based on a ValueListenable.
ValueListenable<String> get previousTitle {
ValueListenable<String?> get previousTitle {
assert(
_previousTitle != null,
'Cannot read the previousTitle for a route that has not yet been installed',
);
return _previousTitle;
return _previousTitle!;
}
@override
void didChangePrevious(Route<dynamic> previousRoute) {
final String previousTitleString = previousRoute is CupertinoRouteTransitionMixin
void didChangePrevious(Route<dynamic>? previousRoute) {
final String? previousTitleString = previousRoute is CupertinoRouteTransitionMixin
? previousRoute.title
: null;
if (_previousTitle == null) {
_previousTitle = ValueNotifier<String>(previousTitleString);
_previousTitle = ValueNotifier<String?>(previousTitleString);
} else {
_previousTitle.value = previousTitleString;
_previousTitle!.value = previousTitleString;
}
super.didChangePrevious(previousRoute);
}
@ -149,10 +146,10 @@ mixin CupertinoRouteTransitionMixin<T> on PageRoute<T> {
Duration get transitionDuration => const Duration(milliseconds: 400);
@override
Color get barrierColor => null;
Color? get barrierColor => null;
@override
String get barrierLabel => null;
String? get barrierLabel => null;
@override
bool canTransitionTo(TransitionRoute<dynamic> nextRoute) {
@ -169,7 +166,7 @@ mixin CupertinoRouteTransitionMixin<T> on PageRoute<T> {
/// * [popGestureEnabled], which returns true if a user-triggered pop gesture
/// would be allowed.
static bool isPopGestureInProgress(PageRoute<dynamic> route) {
return route.navigator.userGestureInProgress;
return route.navigator!.userGestureInProgress;
}
/// True if an iOS-style back swipe pop gesture is currently underway for this route.
@ -210,12 +207,12 @@ mixin CupertinoRouteTransitionMixin<T> on PageRoute<T> {
if (route.fullscreenDialog)
return false;
// If we're in an animation already, we cannot be manually swiped.
if (route.animation.status != AnimationStatus.completed)
if (route.animation!.status != AnimationStatus.completed)
return false;
// If we're being popped into, we also cannot be swiped until the pop above
// it completes. This translates to our secondary animation being
// dismissed.
if (route.secondaryAnimation.status != AnimationStatus.dismissed)
if (route.secondaryAnimation!.status != AnimationStatus.dismissed)
return false;
// If we're in a gesture already, we cannot start another.
if (isPopGestureInProgress(route))
@ -234,7 +231,10 @@ mixin CupertinoRouteTransitionMixin<T> on PageRoute<T> {
child: child,
);
assert(() {
if (child == null) {
// `child` has a non-nullable return type, but might be null when
// running with weak checking, so we need to null check it anyway (and
// ignore the warning that the null-handling logic is dead code).
if (child == null) { // ignore: dead_code
throw FlutterError.fromParts(<DiagnosticsNode>[
ErrorSummary('The builder for route "${settings.name}" returned null.'),
ErrorDescription('Route builders must never return null.'),
@ -252,8 +252,8 @@ mixin CupertinoRouteTransitionMixin<T> on PageRoute<T> {
assert(_isPopGestureEnabled(route));
return _CupertinoBackGestureController<T>(
navigator: route.navigator,
controller: route.controller, // protected access
navigator: route.navigator!,
controller: route.controller!, // protected access
);
}
@ -340,9 +340,9 @@ class CupertinoPageRoute<T> extends PageRoute<T> with CupertinoRouteTransitionMi
/// The [builder], [maintainState], and [fullscreenDialog] arguments must not
/// be null.
CupertinoPageRoute({
@required this.builder,
required this.builder,
this.title,
RouteSettings settings,
RouteSettings? settings,
this.maintainState = true,
bool fullscreenDialog = false,
}) : assert(builder != null),
@ -355,7 +355,7 @@ class CupertinoPageRoute<T> extends PageRoute<T> with CupertinoRouteTransitionMi
final WidgetBuilder builder;
@override
final String title;
final String? title;
@override
final bool maintainState;
@ -370,7 +370,7 @@ class CupertinoPageRoute<T> extends PageRoute<T> with CupertinoRouteTransitionMi
// the content is up to date after page updates.
class _PageBasedCupertinoPageRoute<T> extends PageRoute<T> with CupertinoRouteTransitionMixin<T> {
_PageBasedCupertinoPageRoute({
@required CupertinoPage<T> page,
required CupertinoPage<T> page,
}) : assert(page != null),
assert(opaque),
super(settings: page);
@ -381,7 +381,7 @@ class _PageBasedCupertinoPageRoute<T> extends PageRoute<T> with CupertinoRouteTr
WidgetBuilder get builder => _page.builder;
@override
String get title => _page.title;
String? get title => _page.title;
@override
bool get maintainState => _page.maintainState;
@ -412,13 +412,13 @@ class _PageBasedCupertinoPageRoute<T> extends PageRoute<T> with CupertinoRouteTr
class CupertinoPage<T> extends Page<T> {
/// Creates a cupertino page.
const CupertinoPage({
@required this.builder,
required this.builder,
this.maintainState = true,
this.title,
this.fullscreenDialog = false,
LocalKey key,
String name,
Object arguments,
LocalKey? key,
String? name,
Object? arguments,
}) : assert(builder != null),
assert(maintainState != null),
assert(fullscreenDialog != null),
@ -428,7 +428,7 @@ class CupertinoPage<T> extends Page<T> {
final WidgetBuilder builder;
/// {@macro flutter.cupertino.cupertinoRouteTransitionMixin.title}
final String title;
final String? title;
/// {@macro flutter.widgets.modalRoute.maintainState}
final bool maintainState;
@ -456,11 +456,11 @@ class CupertinoPageTransition extends StatelessWidget {
/// * `linearTransition` is whether to perform the transitions linearly.
/// Used to precisely track back gesture drags.
CupertinoPageTransition({
Key key,
@required Animation<double> primaryRouteAnimation,
@required Animation<double> secondaryRouteAnimation,
@required this.child,
@required bool linearTransition,
Key? key,
required Animation<double> primaryRouteAnimation,
required Animation<double> secondaryRouteAnimation,
required this.child,
required bool linearTransition,
}) : assert(linearTransition != null),
_primaryPositionAnimation =
(linearTransition
@ -508,7 +508,7 @@ class CupertinoPageTransition extends StatelessWidget {
@override
Widget build(BuildContext context) {
assert(debugCheckHasDirectionality(context));
final TextDirection textDirection = Directionality.of(context);
final TextDirection? textDirection = Directionality.of(context);
return SlideTransition(
position: _secondaryPositionAnimation,
textDirection: textDirection,
@ -539,11 +539,11 @@ class CupertinoFullscreenDialogTransition extends StatelessWidget {
/// * `linearTransition` is whether to perform the secondary transition linearly.
/// Used to precisely track back gesture drags.
CupertinoFullscreenDialogTransition({
Key key,
@required Animation<double> primaryRouteAnimation,
@required Animation<double> secondaryRouteAnimation,
@required this.child,
@required bool linearTransition,
Key? key,
required Animation<double> primaryRouteAnimation,
required Animation<double> secondaryRouteAnimation,
required this.child,
required bool linearTransition,
}) : _positionAnimation = CurvedAnimation(
parent: primaryRouteAnimation,
curve: Curves.linearToEaseOut,
@ -572,7 +572,7 @@ class CupertinoFullscreenDialogTransition extends StatelessWidget {
@override
Widget build(BuildContext context) {
assert(debugCheckHasDirectionality(context));
final TextDirection textDirection = Directionality.of(context);
final TextDirection? textDirection = Directionality.of(context);
return SlideTransition(
position: _secondaryPositionAnimation,
textDirection: textDirection,
@ -598,10 +598,10 @@ class CupertinoFullscreenDialogTransition extends StatelessWidget {
/// detector is associated.
class _CupertinoBackGestureDetector<T> extends StatefulWidget {
const _CupertinoBackGestureDetector({
Key key,
@required this.enabledCallback,
@required this.onStartPopGesture,
@required this.child,
Key? key,
required this.enabledCallback,
required this.onStartPopGesture,
required this.child,
}) : assert(enabledCallback != null),
assert(onStartPopGesture != null),
assert(child != null),
@ -618,9 +618,9 @@ class _CupertinoBackGestureDetector<T> extends StatefulWidget {
}
class _CupertinoBackGestureDetectorState<T> extends State<_CupertinoBackGestureDetector<T>> {
_CupertinoBackGestureController<T> _backGestureController;
_CupertinoBackGestureController<T>? _backGestureController;
HorizontalDragGestureRecognizer _recognizer;
late HorizontalDragGestureRecognizer _recognizer;
@override
void initState() {
@ -647,13 +647,13 @@ class _CupertinoBackGestureDetectorState<T> extends State<_CupertinoBackGestureD
void _handleDragUpdate(DragUpdateDetails details) {
assert(mounted);
assert(_backGestureController != null);
_backGestureController.dragUpdate(_convertToLogical(details.primaryDelta / context.size.width));
_backGestureController!.dragUpdate(_convertToLogical(details.primaryDelta! / context.size!.width));
}
void _handleDragEnd(DragEndDetails details) {
assert(mounted);
assert(_backGestureController != null);
_backGestureController.dragEnd(_convertToLogical(details.velocity.pixelsPerSecond.dx / context.size.width));
_backGestureController!.dragEnd(_convertToLogical(details.velocity.pixelsPerSecond.dx / context.size!.width));
_backGestureController = null;
}
@ -671,13 +671,12 @@ class _CupertinoBackGestureDetectorState<T> extends State<_CupertinoBackGestureD
}
double _convertToLogical(double value) {
switch (Directionality.of(context)) {
switch (Directionality.of(context)!) {
case TextDirection.rtl:
return -value;
case TextDirection.ltr:
return value;
}
return null;
}
@override
@ -686,8 +685,8 @@ class _CupertinoBackGestureDetectorState<T> extends State<_CupertinoBackGestureD
// For devices with notches, the drag area needs to be larger on the side
// that has the notch.
double dragAreaWidth = Directionality.of(context) == TextDirection.ltr ?
MediaQuery.of(context).padding.left :
MediaQuery.of(context).padding.right;
MediaQuery.of(context)!.padding.left :
MediaQuery.of(context)!.padding.right;
dragAreaWidth = max(dragAreaWidth, _kBackGestureWidth);
return Stack(
fit: StackFit.passthrough,
@ -725,8 +724,8 @@ class _CupertinoBackGestureController<T> {
///
/// The [navigator] and [controller] arguments must not be null.
_CupertinoBackGestureController({
@required this.navigator,
@required this.controller,
required this.navigator,
required this.controller,
}) : assert(navigator != null),
assert(controller != null) {
navigator.didStartUserGesture();
@ -766,7 +765,7 @@ class _CupertinoBackGestureController<T> {
// We want to cap the animation time, but we want to use a linear curve
// to determine it.
final int droppedPageForwardAnimationTime = min(
lerpDouble(_kMaxDroppedSwipePageForwardAnimationTime, 0, controller.value).floor(),
lerpDouble(_kMaxDroppedSwipePageForwardAnimationTime, 0, controller.value)!.floor(),
_kMaxPageBackAnimationTime,
);
controller.animateTo(1.0, duration: Duration(milliseconds: droppedPageForwardAnimationTime), curve: animationCurve);
@ -777,7 +776,7 @@ class _CupertinoBackGestureController<T> {
// The popping may have finished inline if already at the target destination.
if (controller.isAnimating) {
// Otherwise, use a custom popping animation duration and curve.
final int droppedPageBackAnimationTime = lerpDouble(0, _kMaxDroppedSwipePageForwardAnimationTime, controller.value).floor();
final int droppedPageBackAnimationTime = lerpDouble(0, _kMaxDroppedSwipePageForwardAnimationTime, controller.value)!.floor();
controller.animateBack(0.0, duration: Duration(milliseconds: droppedPageBackAnimationTime), curve: animationCurve);
}
}
@ -786,7 +785,7 @@ class _CupertinoBackGestureController<T> {
// Keep the userGestureInProgress in true state so we don't change the
// curve of the page transition mid-flight since CupertinoPageTransition
// depends on userGestureInProgress.
AnimationStatusListener animationStatusCallback;
late AnimationStatusListener animationStatusCallback;
animationStatusCallback = (AnimationStatus status) {
navigator.didStopUserGesture();
controller.removeStatusListener(animationStatusCallback);
@ -818,7 +817,7 @@ class _CupertinoEdgeShadowDecoration extends Decoration {
// A gradient to draw to the left of the box being decorated.
// Alignments are relative to the original box translated one box
// width to the left.
final LinearGradient edgeGradient;
final LinearGradient? edgeGradient;
// Linearly interpolate between two edge shadow decorations decorations.
//
@ -837,9 +836,9 @@ class _CupertinoEdgeShadowDecoration extends Decoration {
// See also:
//
// * [Decoration.lerp].
static _CupertinoEdgeShadowDecoration lerp(
_CupertinoEdgeShadowDecoration a,
_CupertinoEdgeShadowDecoration b,
static _CupertinoEdgeShadowDecoration? lerp(
_CupertinoEdgeShadowDecoration? a,
_CupertinoEdgeShadowDecoration? b,
double t,
) {
assert(t != null);
@ -851,21 +850,21 @@ class _CupertinoEdgeShadowDecoration extends Decoration {
}
@override
_CupertinoEdgeShadowDecoration lerpFrom(Decoration a, double t) {
_CupertinoEdgeShadowDecoration lerpFrom(Decoration? a, double t) {
if (a is _CupertinoEdgeShadowDecoration)
return _CupertinoEdgeShadowDecoration.lerp(a, this, t);
return _CupertinoEdgeShadowDecoration.lerp(null, this, t);
return _CupertinoEdgeShadowDecoration.lerp(a, this, t)!;
return _CupertinoEdgeShadowDecoration.lerp(null, this, t)!;
}
@override
_CupertinoEdgeShadowDecoration lerpTo(Decoration b, double t) {
_CupertinoEdgeShadowDecoration lerpTo(Decoration? b, double t) {
if (b is _CupertinoEdgeShadowDecoration)
return _CupertinoEdgeShadowDecoration.lerp(this, b, t);
return _CupertinoEdgeShadowDecoration.lerp(this, null, t);
return _CupertinoEdgeShadowDecoration.lerp(this, b, t)!;
return _CupertinoEdgeShadowDecoration.lerp(this, null, t)!;
}
@override
_CupertinoEdgeShadowPainter createBoxPainter([ VoidCallback onChanged ]) {
_CupertinoEdgeShadowPainter createBoxPainter([ VoidCallback? onChanged ]) {
return _CupertinoEdgeShadowPainter(this, onChanged);
}
@ -891,7 +890,7 @@ class _CupertinoEdgeShadowDecoration extends Decoration {
class _CupertinoEdgeShadowPainter extends BoxPainter {
_CupertinoEdgeShadowPainter(
this._decoration,
VoidCallback onChange,
VoidCallback? onChange,
) : assert(_decoration != null),
super(onChange);
@ -899,23 +898,23 @@ class _CupertinoEdgeShadowPainter extends BoxPainter {
@override
void paint(Canvas canvas, Offset offset, ImageConfiguration configuration) {
final LinearGradient gradient = _decoration.edgeGradient;
final LinearGradient? gradient = _decoration.edgeGradient;
if (gradient == null)
return;
// The drawable space for the gradient is a rect with the same size as
// its parent box one box width on the start side of the box.
final TextDirection textDirection = configuration.textDirection;
final TextDirection? textDirection = configuration.textDirection;
assert(textDirection != null);
double deltaX;
switch (textDirection) {
switch (textDirection!) {
case TextDirection.rtl:
deltaX = configuration.size.width;
deltaX = configuration.size!.width;
break;
case TextDirection.ltr:
deltaX = -configuration.size.width;
deltaX = -configuration.size!.width;
break;
}
final Rect rect = (offset & configuration.size).translate(deltaX, 0.0);
final Rect rect = (offset & configuration.size!).translate(deltaX, 0.0);
final Paint paint = Paint()
..shader = gradient.createShader(rect, textDirection: textDirection);
@ -925,12 +924,12 @@ class _CupertinoEdgeShadowPainter extends BoxPainter {
class _CupertinoModalPopupRoute<T> extends PopupRoute<T> {
_CupertinoModalPopupRoute({
this.barrierColor,
this.barrierLabel,
this.builder,
bool semanticsDismissible,
ImageFilter filter,
RouteSettings settings,
required this.barrierColor,
required this.barrierLabel,
required this.builder,
bool? semanticsDismissible,
required ImageFilter? filter,
RouteSettings? settings,
}) : super(
filter: filter,
settings: settings,
@ -939,13 +938,13 @@ class _CupertinoModalPopupRoute<T> extends PopupRoute<T> {
}
final WidgetBuilder builder;
bool _semanticsDismissible;
bool? _semanticsDismissible;
@override
final String barrierLabel;
@override
final Color barrierColor;
final Color? barrierColor;
@override
bool get barrierDismissible => true;
@ -956,9 +955,9 @@ class _CupertinoModalPopupRoute<T> extends PopupRoute<T> {
@override
Duration get transitionDuration => _kModalPopupTransitionDuration;
Animation<double> _animation;
Animation<double>? _animation;
Tween<Offset> _offsetTween;
late Tween<Offset> _offsetTween;
@override
Animation<double> createAnimation() {
@ -975,7 +974,7 @@ class _CupertinoModalPopupRoute<T> extends PopupRoute<T> {
begin: const Offset(0.0, 1.0),
end: const Offset(0.0, 0.0),
);
return _animation;
return _animation!;
}
@override
@ -991,7 +990,7 @@ class _CupertinoModalPopupRoute<T> extends PopupRoute<T> {
return Align(
alignment: Alignment.bottomCenter,
child: FractionalTranslation(
translation: _offsetTween.evaluate(_animation),
translation: _offsetTween.evaluate(_animation!),
child: child,
),
);
@ -1030,14 +1029,14 @@ class _CupertinoModalPopupRoute<T> extends PopupRoute<T> {
/// `builder` argument to [showCupertinoModalPopup].
/// * <https://developer.apple.com/design/human-interface-guidelines/ios/views/action-sheets/>
Future<T> showCupertinoModalPopup<T>({
@required BuildContext context,
@required WidgetBuilder builder,
ImageFilter filter,
required BuildContext context,
required WidgetBuilder builder,
ImageFilter? filter,
bool useRootNavigator = true,
bool semanticsDismissible,
bool? semanticsDismissible,
}) {
assert(useRootNavigator != null);
return Navigator.of(context, rootNavigator: useRootNavigator).push(
return Navigator.of(context, rootNavigator: useRootNavigator)!.push(
_CupertinoModalPopupRoute<T>(
barrierColor: CupertinoDynamicColor.resolve(_kModalBarrierColor, context),
barrierLabel: 'Dismiss',
@ -1110,19 +1109,19 @@ Widget _buildCupertinoDialogTransitions(BuildContext context, Animation<double>
/// * [showGeneralDialog], which allows for customization of the dialog popup.
/// * <https://developer.apple.com/ios/human-interface-guidelines/views/alerts/>
Future<T> showCupertinoDialog<T>({
@required BuildContext context,
@required WidgetBuilder builder,
required BuildContext context,
required WidgetBuilder builder,
bool useRootNavigator = true,
bool barrierDismissible = false,
RouteSettings routeSettings,
RouteSettings? routeSettings,
}) {
assert(builder != null);
assert(useRootNavigator != null);
return showGeneralDialog(
context: context,
barrierDismissible: barrierDismissible,
barrierLabel: CupertinoLocalizations.of(context).modalBarrierDismissLabel,
barrierColor: CupertinoDynamicColor.resolve(_kModalBarrierColor, context),
barrierLabel: CupertinoLocalizations.of(context)!.modalBarrierDismissLabel,
barrierColor: CupertinoDynamicColor.resolve(_kModalBarrierColor, context)!,
// This transition duration was eyeballed comparing with iOS
transitionDuration: const Duration(milliseconds: 250),
pageBuilder: (BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {

View file

@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:async';
import 'package:flutter/gestures.dart';
@ -56,14 +54,14 @@ class CupertinoScrollbar extends StatefulWidget {
/// The [child] should be a source of [ScrollNotification] notifications,
/// typically a [Scrollable] widget.
const CupertinoScrollbar({
Key key,
Key? key,
this.controller,
this.isAlwaysShown = false,
this.thickness = defaultThickness,
this.thicknessWhileDragging = defaultThicknessWhileDragging,
this.radius = defaultRadius,
this.radiusWhileDragging = defaultRadiusWhileDragging,
@required this.child,
required this.child,
}) : assert(thickness != null),
assert(thickness < double.infinity),
assert(thicknessWhileDragging != null),
@ -145,7 +143,7 @@ class CupertinoScrollbar extends StatefulWidget {
/// ```
/// {@end-tool}
/// {@endtemplate}
final ScrollController controller;
final ScrollController? controller;
/// {@template flutter.cupertino.cupertinoScrollbar.isAlwaysShown}
/// Indicates whether the [Scrollbar] should always be visible.
@ -237,25 +235,25 @@ class CupertinoScrollbar extends StatefulWidget {
class _CupertinoScrollbarState extends State<CupertinoScrollbar> with TickerProviderStateMixin {
final GlobalKey _customPaintKey = GlobalKey();
ScrollbarPainter _painter;
ScrollbarPainter? _painter;
AnimationController _fadeoutAnimationController;
Animation<double> _fadeoutOpacityAnimation;
AnimationController _thicknessAnimationController;
Timer _fadeoutTimer;
double _dragScrollbarPositionY;
Drag _drag;
late AnimationController _fadeoutAnimationController;
late Animation<double> _fadeoutOpacityAnimation;
late AnimationController _thicknessAnimationController;
Timer? _fadeoutTimer;
double? _dragScrollbarPositionY;
Drag? _drag;
double get _thickness {
return widget.thickness + _thicknessAnimationController.value * (widget.thicknessWhileDragging - widget.thickness);
}
Radius get _radius {
return Radius.lerp(widget.radius, widget.radiusWhileDragging, _thicknessAnimationController.value);
return Radius.lerp(widget.radius, widget.radiusWhileDragging, _thicknessAnimationController.value)!;
}
ScrollController _currentController;
ScrollController get _controller =>
ScrollController? _currentController;
ScrollController? get _controller =>
widget.controller ?? PrimaryScrollController.of(context);
@override
@ -274,7 +272,7 @@ class _CupertinoScrollbarState extends State<CupertinoScrollbar> with TickerProv
duration: _kScrollbarResizeDuration,
);
_thicknessAnimationController.addListener(() {
_painter.updateThickness(_thickness, _radius);
_painter!.updateThickness(_thickness, _radius);
});
}
@ -284,10 +282,10 @@ class _CupertinoScrollbarState extends State<CupertinoScrollbar> with TickerProv
if (_painter == null) {
_painter = _buildCupertinoScrollbarPainter(context);
} else {
_painter
..textDirection = Directionality.of(context)
..color = CupertinoDynamicColor.resolve(_kScrollbarColor, context)
..padding = MediaQuery.of(context).padding;
_painter!
..textDirection = Directionality.of(context)!
..color = CupertinoDynamicColor.resolve(_kScrollbarColor, context)!
..padding = MediaQuery.of(context)!.padding;
}
_triggerScrollbar();
}
@ -296,7 +294,7 @@ class _CupertinoScrollbarState extends State<CupertinoScrollbar> with TickerProv
void didUpdateWidget(CupertinoScrollbar oldWidget) {
super.didUpdateWidget(oldWidget);
assert(_painter != null);
_painter.updateThickness(_thickness, _radius);
_painter!.updateThickness(_thickness, _radius);
if (widget.isAlwaysShown != oldWidget.isAlwaysShown) {
if (widget.isAlwaysShown == true) {
_triggerScrollbar();
@ -310,14 +308,14 @@ class _CupertinoScrollbarState extends State<CupertinoScrollbar> with TickerProv
/// Returns a [ScrollbarPainter] visually styled like the iOS scrollbar.
ScrollbarPainter _buildCupertinoScrollbarPainter(BuildContext context) {
return ScrollbarPainter(
color: CupertinoDynamicColor.resolve(_kScrollbarColor, context),
textDirection: Directionality.of(context),
color: CupertinoDynamicColor.resolve(_kScrollbarColor, context)!,
textDirection: Directionality.of(context)!,
thickness: _thickness,
fadeoutOpacityAnimation: _fadeoutOpacityAnimation,
mainAxisMargin: _kScrollbarMainAxisMargin,
crossAxisMargin: _kScrollbarCrossAxisMargin,
radius: _radius,
padding: MediaQuery.of(context).padding,
padding: MediaQuery.of(context)!.padding,
minLength: _kScrollbarMinLength,
minOverscrollLength: _kScrollbarMinOverscrollLength,
);
@ -327,10 +325,10 @@ class _CupertinoScrollbarState extends State<CupertinoScrollbar> with TickerProv
// show immediately when isAlwaysShown is true. A scroll event is required in
// order to paint the thumb.
void _triggerScrollbar() {
WidgetsBinding.instance.addPostFrameCallback((Duration duration) {
WidgetsBinding.instance!.addPostFrameCallback((Duration duration) {
if (widget.isAlwaysShown) {
_fadeoutTimer?.cancel();
widget.controller.position.didUpdateScrollPositionBy(0);
widget.controller!.position.didUpdateScrollPositionBy(0);
}
});
}
@ -342,18 +340,18 @@ class _CupertinoScrollbarState extends State<CupertinoScrollbar> with TickerProv
// Convert primaryDelta, the amount that the scrollbar moved since the last
// time _dragScrollbar was called, into the coordinate space of the scroll
// position, and create/update the drag event with that position.
final double scrollOffsetLocal = _painter.getTrackToScroll(primaryDelta);
final double scrollOffsetGlobal = scrollOffsetLocal + _currentController.position.pixels;
final double scrollOffsetLocal = _painter!.getTrackToScroll(primaryDelta);
final double scrollOffsetGlobal = scrollOffsetLocal + _currentController!.position.pixels;
if (_drag == null) {
_drag = _currentController.position.drag(
_drag = _currentController!.position.drag(
DragStartDetails(
globalPosition: Offset(0.0, scrollOffsetGlobal),
),
() {},
);
} else {
_drag.update(DragUpdateDetails(
_drag!.update(DragUpdateDetails(
globalPosition: Offset(0.0, scrollOffsetGlobal),
delta: Offset(0.0, -scrollOffsetLocal),
primaryDelta: -scrollOffsetLocal,
@ -373,7 +371,7 @@ class _CupertinoScrollbarState extends State<CupertinoScrollbar> with TickerProv
bool _checkVertical() {
try {
return _currentController.position.axis == Axis.vertical;
return _currentController!.position.axis == Axis.vertical;
} catch (_) {
// Ignore the gesture if we cannot determine the direction.
return false;
@ -410,7 +408,7 @@ class _CupertinoScrollbarState extends State<CupertinoScrollbar> with TickerProv
if (!_checkVertical()) {
return;
}
_dragScrollbar(details.localPosition.dy - _dragScrollbarPositionY);
_dragScrollbar(details.localPosition.dy - _dragScrollbarPositionY!);
_dragScrollbarPositionY = details.localPosition.dy;
}
@ -430,7 +428,7 @@ class _CupertinoScrollbarState extends State<CupertinoScrollbar> with TickerProv
_startFadeoutTimer();
_thicknessAnimationController.reverse();
_dragScrollbarPositionY = null;
final double scrollVelocityY = _painter.getTrackToScroll(trackVelocityY);
final double scrollVelocityY = _painter!.getTrackToScroll(trackVelocityY);
_drag?.end(DragEndDetails(
primaryVelocity: -scrollVelocityY,
velocity: Velocity(
@ -457,7 +455,7 @@ class _CupertinoScrollbarState extends State<CupertinoScrollbar> with TickerProv
}
_fadeoutTimer?.cancel();
_painter.update(notification.metrics, notification.metrics.axisDirection);
_painter!.update(notification.metrics, notification.metrics.axisDirection);
} else if (notification is ScrollEndNotification) {
// On iOS, the scrollbar can only go away once the user lifted the finger.
if (_dragScrollbarPositionY == null) {
@ -496,7 +494,7 @@ class _CupertinoScrollbarState extends State<CupertinoScrollbar> with TickerProv
_fadeoutAnimationController.dispose();
_thicknessAnimationController.dispose();
_fadeoutTimer?.cancel();
_painter.dispose();
_painter!.dispose();
super.dispose();
}
@ -522,10 +520,10 @@ class _CupertinoScrollbarState extends State<CupertinoScrollbar> with TickerProv
// thumb and ignores everything else.
class _ThumbPressGestureRecognizer extends LongPressGestureRecognizer {
_ThumbPressGestureRecognizer({
double postAcceptSlopTolerance,
PointerDeviceKind kind,
Object debugOwner,
GlobalKey customPaintKey,
double? postAcceptSlopTolerance,
PointerDeviceKind? kind,
required Object debugOwner,
required GlobalKey customPaintKey,
}) : _customPaintKey = customPaintKey,
super(
postAcceptSlopTolerance: postAcceptSlopTolerance,
@ -552,9 +550,9 @@ bool _hitTestInteractive(GlobalKey customPaintKey, Offset offset) {
if (customPaintKey.currentContext == null) {
return false;
}
final CustomPaint customPaint = customPaintKey.currentContext.widget as CustomPaint;
final CustomPaint customPaint = customPaintKey.currentContext!.widget as CustomPaint;
final ScrollbarPainter painter = customPaint.foregroundPainter as ScrollbarPainter;
final RenderBox renderBox = customPaintKey.currentContext.findRenderObject() as RenderBox;
final RenderBox renderBox = customPaintKey.currentContext!.findRenderObject() as RenderBox;
final Offset localOffset = renderBox.globalToLocal(offset);
return painter.hitTestInteractive(localOffset);
}

View file

@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:ui' show lerpDouble;
import 'package:flutter/foundation.dart';
@ -58,9 +56,9 @@ class CupertinoSwitch extends StatefulWidget {
/// The [value] parameter must not be null.
/// The [dragStartBehavior] parameter defaults to [DragStartBehavior.start] and must not be null.
const CupertinoSwitch({
Key key,
@required this.value,
@required this.onChanged,
Key? key,
required this.value,
required this.onChanged,
this.activeColor,
this.trackColor,
this.dragStartBehavior = DragStartBehavior.start,
@ -95,18 +93,18 @@ class CupertinoSwitch extends StatefulWidget {
/// },
/// )
/// ```
final ValueChanged<bool> onChanged;
final ValueChanged<bool>? onChanged;
/// The color to use when this switch is on.
///
/// Defaults to [CupertinoColors.systemGreen] when null and ignores
/// the [CupertinoTheme] in accordance to native iOS behavior.
final Color activeColor;
final Color? activeColor;
/// The color to use for the background when the switch is off.
///
/// Defaults to [CupertinoColors.secondarySystemFill] when null.
final Color trackColor;
final Color? trackColor;
/// {@template flutter.cupertino.switch.dragStartBehavior}
/// Determines the way that drag start behavior is handled.
@ -142,14 +140,14 @@ class CupertinoSwitch extends StatefulWidget {
}
class _CupertinoSwitchState extends State<CupertinoSwitch> with TickerProviderStateMixin {
TapGestureRecognizer _tap;
HorizontalDragGestureRecognizer _drag;
late TapGestureRecognizer _tap;
late HorizontalDragGestureRecognizer _drag;
AnimationController _positionController;
CurvedAnimation position;
late AnimationController _positionController;
late CurvedAnimation position;
AnimationController _reactionController;
Animation<double> _reaction;
late AnimationController _reactionController;
late Animation<double> _reaction;
bool get isInteractive => widget.onChanged != null;
@ -209,8 +207,8 @@ class _CupertinoSwitchState extends State<CupertinoSwitch> with TickerProviderSt
void _resumePositionAnimation({ bool isLinear = true }) {
needsPositionAnimation = false;
position
..curve = isLinear ? null : Curves.ease
..reverseCurve = isLinear ? null : Curves.ease.flipped;
..curve = isLinear ? Curves.linear : Curves.ease
..reverseCurve = isLinear ? Curves.linear : Curves.ease.flipped;
if (widget.value)
_positionController.forward();
else
@ -225,7 +223,7 @@ class _CupertinoSwitchState extends State<CupertinoSwitch> with TickerProviderSt
void _handleTap() {
if (isInteractive) {
widget.onChanged(!widget.value);
widget.onChanged!(!widget.value);
_emitVibration();
}
}
@ -253,10 +251,10 @@ class _CupertinoSwitchState extends State<CupertinoSwitch> with TickerProviderSt
void _handleDragUpdate(DragUpdateDetails details) {
if (isInteractive) {
position
..curve = null
..reverseCurve = null;
final double delta = details.primaryDelta / _kTrackInnerLength;
switch (Directionality.of(context)) {
..curve = Curves.linear
..reverseCurve = Curves.linear;
final double delta = details.primaryDelta! / _kTrackInnerLength;
switch (Directionality.of(context)!) {
case TextDirection.rtl:
_positionController.value -= delta;
break;
@ -272,7 +270,7 @@ class _CupertinoSwitchState extends State<CupertinoSwitch> with TickerProviderSt
setState(() { needsPositionAnimation = true; });
// Call onChanged when the user's intent to change value is clear.
if (position.value >= 0.5 != widget.value)
widget.onChanged(!widget.value);
widget.onChanged!(!widget.value);
_reactionController.reverse();
}
@ -301,10 +299,10 @@ class _CupertinoSwitchState extends State<CupertinoSwitch> with TickerProviderSt
activeColor: CupertinoDynamicColor.resolve(
widget.activeColor ?? CupertinoColors.systemGreen,
context,
),
trackColor: CupertinoDynamicColor.resolve(widget.trackColor ?? CupertinoColors.secondarySystemFill, context),
)!,
trackColor: CupertinoDynamicColor.resolve(widget.trackColor ?? CupertinoColors.secondarySystemFill, context)!,
onChanged: widget.onChanged,
textDirection: Directionality.of(context),
textDirection: Directionality.of(context)!,
state: this,
),
);
@ -323,19 +321,19 @@ class _CupertinoSwitchState extends State<CupertinoSwitch> with TickerProviderSt
class _CupertinoSwitchRenderObjectWidget extends LeafRenderObjectWidget {
const _CupertinoSwitchRenderObjectWidget({
Key key,
this.value,
this.activeColor,
this.trackColor,
this.onChanged,
this.textDirection,
this.state,
Key? key,
required this.value,
required this.activeColor,
required this.trackColor,
required this.onChanged,
required this.textDirection,
required this.state,
}) : super(key: key);
final bool value;
final Color activeColor;
final Color trackColor;
final ValueChanged<bool> onChanged;
final ValueChanged<bool>? onChanged;
final _CupertinoSwitchState state;
final TextDirection textDirection;
@ -378,12 +376,12 @@ const Duration _kToggleDuration = Duration(milliseconds: 200);
class _RenderCupertinoSwitch extends RenderConstrainedBox {
_RenderCupertinoSwitch({
@required bool value,
@required Color activeColor,
@required Color trackColor,
ValueChanged<bool> onChanged,
@required TextDirection textDirection,
@required _CupertinoSwitchState state,
required bool value,
required Color activeColor,
required Color trackColor,
ValueChanged<bool>? onChanged,
required TextDirection textDirection,
required _CupertinoSwitchState state,
}) : assert(value != null),
assert(activeColor != null),
assert(state != null),
@ -430,9 +428,9 @@ class _RenderCupertinoSwitch extends RenderConstrainedBox {
markNeedsPaint();
}
ValueChanged<bool> get onChanged => _onChanged;
ValueChanged<bool> _onChanged;
set onChanged(ValueChanged<bool> value) {
ValueChanged<bool>? get onChanged => _onChanged;
ValueChanged<bool>? _onChanged;
set onChanged(ValueChanged<bool>? value) {
if (value == _onChanged)
return;
final bool wasInteractive = isInteractive;
@ -496,7 +494,7 @@ class _RenderCupertinoSwitch extends RenderConstrainedBox {
}
final Paint paint = Paint()
..color = Color.lerp(trackColor, activeColor, currentValue);
..color = Color.lerp(trackColor, activeColor, currentValue)!;
final Rect trackRect = Rect.fromLTWH(
offset.dx + (size.width - _kTrackWidth) / 2.0,
@ -512,12 +510,12 @@ class _RenderCupertinoSwitch extends RenderConstrainedBox {
trackRect.left + _kTrackInnerStart - CupertinoThumbPainter.radius,
trackRect.left + _kTrackInnerEnd - CupertinoThumbPainter.radius - currentThumbExtension,
visualPosition,
);
)!;
final double thumbRight = lerpDouble(
trackRect.left + _kTrackInnerStart + CupertinoThumbPainter.radius + currentThumbExtension,
trackRect.left + _kTrackInnerEnd + CupertinoThumbPainter.radius,
visualPosition,
);
)!;
final double thumbCenterY = offset.dy + size.height / 2.0;
final Rect thumbBounds = Rect.fromLTRB(
thumbLeft,