mirror of
https://github.com/flutter/flutter
synced 2024-10-13 03:32:55 +00:00
migrate some cupertino files to nullsafety (#66424)
* migrate some cupertino files to nullsafety * address review comments
This commit is contained in:
parent
707aa49e42
commit
29fae79c72
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in a new issue