From 8743bf8b5c256f18623e1a851331e1353ba0362f Mon Sep 17 00:00:00 2001 From: yuanjunliang Date: Wed, 12 Jan 2022 15:55:49 +0800 Subject: [PATCH 1/2] migrate actionsheet into null-safe --- .../actionsheet/brn_common_action_sheet.dart | 76 ++++---- .../brn_selected_list_action_sheet.dart | 177 +++++++++--------- .../actionsheet/brn_share_action_sheet.dart | 50 +++-- 3 files changed, 145 insertions(+), 158 deletions(-) diff --git a/lib/src/components/actionsheet/brn_common_action_sheet.dart b/lib/src/components/actionsheet/brn_common_action_sheet.dart index 9a45ca0b..ab18f617 100644 --- a/lib/src/components/actionsheet/brn_common_action_sheet.dart +++ b/lib/src/components/actionsheet/brn_common_action_sheet.dart @@ -1,5 +1,3 @@ -// @dart=2.9 - import 'dart:ui'; import 'package:bruno/src/theme/brn_theme_configurator.dart'; @@ -28,16 +26,16 @@ class BrnCommonActionSheetItem { String title; /// 辅助信息 - String desc; + String? desc; /// 样式 [BrnActionSheetActionStyle] final BrnCommonActionSheetItemStyle actionStyle; /// 主标题文本样式 - final TextStyle titleStyle; + final TextStyle? titleStyle; /// 辅助信息文本样式 - final TextStyle descStyle; + final TextStyle? descStyle; BrnCommonActionSheetItem( this.title, { @@ -57,19 +55,19 @@ class BrnCommonActionSheet extends StatelessWidget { final List actions; /// ActionSheet 标题 - final String title; + final String? title; /// title区域widget, 与 title 字段互斥,当 titleWidget 不为 null 时优先使用 titleWidget。 - final Widget titleWidget; + final Widget? titleWidget; /// Action 之间分割线颜色,默认值 Color(0xfff0f0f0) - final Color separatorLineColor; + final Color? separatorLineColor; /// 取消按钮与 Action 之间的分割线的颜色,默认值 Color(0xfff8f8f8) final Color spaceColor; /// 取消按钮文本 - final String cancelTitle; + final String? cancelTitle; /// 标题最大行数,默认为2 final int maxTitleLines; @@ -79,16 +77,16 @@ class BrnCommonActionSheet extends StatelessWidget { final double maxSheetHeight; /// Action Item 的点击事件 - final BrnCommonActionSheetItemClickCallBack clickCallBack; + final BrnCommonActionSheetItemClickCallBack? clickCallBack; /// Action Item 点击事件拦截回调 - final BrnCommonActionSheetItemClickInterceptor onItemClickInterceptor; + final BrnCommonActionSheetItemClickInterceptor? onItemClickInterceptor; /// 主题定制 - BrnActionSheetConfig themeData; + BrnActionSheetConfig? themeData; BrnCommonActionSheet({ - @required this.actions, + required this.actions, this.title, this.titleWidget, this.cancelTitle, @@ -99,10 +97,10 @@ class BrnCommonActionSheet extends StatelessWidget { this.maxSheetHeight = 0, this.onItemClickInterceptor, this.themeData, - }) : assert(actions != null) { + }) { themeData ??= BrnActionSheetConfig(); themeData = BrnThemeConfigurator.instance - .getConfig(configId: themeData.configId) + .getConfig(configId: themeData!.configId) .actionSheetConfig .merge(themeData); } @@ -124,8 +122,8 @@ class BrnCommonActionSheet extends StatelessWidget { color: Colors.white, shape: RoundedRectangleBorder( borderRadius: BorderRadius.only( - topLeft: Radius.circular(themeData.topRadius), - topRight: Radius.circular(themeData.topRadius), + topLeft: Radius.circular(themeData!.topRadius), + topRight: Radius.circular(themeData!.topRadius), ), ), ), @@ -137,11 +135,11 @@ class BrnCommonActionSheet extends StatelessWidget { /// 构建actionSheet的按钮 Widget _configActionWidgets(BuildContext context, double _maxSheetHeight) { - List widgets = List(); + List widgets = []; // 构建整体标题 if (titleWidget != null) { // 如果传入了则直接使用 - widgets.add(titleWidget); + widgets.add(titleWidget!); } else if (title != null && title.toString().trim() != "") { // 如果只传入title则根据文案构建默认title widgets.add(_configTitleActions()); @@ -149,7 +147,7 @@ class BrnCommonActionSheet extends StatelessWidget { widgets.add(_configListActions(context)); // 添加间隔 widgets.add(Divider( - color: spaceColor ?? Color(0xfff8f8f8), + color: spaceColor, thickness: 8, height: 8, )); @@ -170,13 +168,13 @@ class BrnCommonActionSheet extends StatelessWidget { return Column( children: [ Container( - padding: themeData.titlePadding, + padding: themeData!.titlePadding, child: Center( child: Text( - title, + title!, textAlign: TextAlign.center, maxLines: maxTitleLines, - style: themeData.titleStyle.generateTextStyle(), + style: themeData!.titleStyle.generateTextStyle(), ), ), ), @@ -184,7 +182,7 @@ class BrnCommonActionSheet extends StatelessWidget { //有标题则添加分割线 thickness: 1, height: 1, - color: separatorLineColor ?? themeData.commonConfig.dividerColorBase, + color: separatorLineColor ?? themeData!.commonConfig.dividerColorBase, ), ], ); @@ -192,22 +190,22 @@ class BrnCommonActionSheet extends StatelessWidget { /// 构建列表widget Widget _configListActions(BuildContext context) { - List tiles = List(); + List tiles = []; //构建列表内容 for (int index = 0; index < actions.length; index++) { tiles.add( GestureDetector( behavior: HitTestBehavior.opaque, child: Container( - padding: themeData.contentPadding, + padding: themeData!.contentPadding, child: _configTile(actions[index]), ), onTap: () { if (onItemClickInterceptor == null || - !onItemClickInterceptor(index, actions[index])) { + !onItemClickInterceptor!(index, actions[index])) { // 推荐使用回调方法处理点击事件!!!!!!!!!! if (clickCallBack != null) { - clickCallBack(index, actions[index]); + clickCallBack!(index, actions[index]); } // 如果未拦截,则pop掉当前页面,并且携带信息(不建议使用此信息进行点击时间处理) Navigator.of(context).pop([index, actions[index]]); @@ -218,7 +216,7 @@ class BrnCommonActionSheet extends StatelessWidget { tiles.add(Divider( thickness: 1, height: 1, - color: separatorLineColor ?? themeData.commonConfig.dividerColorBase, + color: separatorLineColor ?? themeData!.commonConfig.dividerColorBase, )); } return Flexible( @@ -233,7 +231,7 @@ class BrnCommonActionSheet extends StatelessWidget { // 配置每个选项内部信息 // action 每个item配置项 [BrnCommonActionSheetItem] Widget _configTile(BrnCommonActionSheetItem action) { - List tileElements = List(); + List tileElements = []; bool hasTitle = false; // 如果有标题则添加标题 if (action.title != null) { @@ -243,10 +241,10 @@ class BrnCommonActionSheet extends StatelessWidget { maxLines: 1, style: action.titleStyle ?? (action.actionStyle == BrnCommonActionSheetItemStyle.alert - ? this.themeData.itemTitleStyleAlert.generateTextStyle() + ? this.themeData!.itemTitleStyleAlert.generateTextStyle() : (action.actionStyle == BrnCommonActionSheetItemStyle.link - ? this.themeData.itemTitleStyleLink.generateTextStyle() - : this.themeData.itemTitleStyle.generateTextStyle())), + ? this.themeData!.itemTitleStyleLink.generateTextStyle() + : this.themeData!.itemTitleStyle.generateTextStyle())), ), )); hasTitle = true; @@ -262,15 +260,15 @@ class BrnCommonActionSheet extends StatelessWidget { tileElements.add( Center( child: Text( - action.desc, + action.desc!, textAlign: TextAlign.center, maxLines: 1, style: action.descStyle ?? (action.actionStyle == BrnCommonActionSheetItemStyle.alert - ? this.themeData.itemDescStyleAlert.generateTextStyle() + ? this.themeData!.itemDescStyleAlert.generateTextStyle() : (action.actionStyle == BrnCommonActionSheetItemStyle.link - ? this.themeData.itemDescStyleLink.generateTextStyle() - : this.themeData.itemDescStyle.generateTextStyle())), + ? this.themeData!.itemDescStyleLink.generateTextStyle() + : this.themeData!.itemDescStyle.generateTextStyle())), ), ), ); @@ -294,8 +292,8 @@ class BrnCommonActionSheet extends StatelessWidget { padding: EdgeInsets.only(top: 12, bottom: 12), child: Center( child: Text( - (cancelTitle != null) ? cancelTitle : "取消", - style: this.themeData.cancelStyle.generateTextStyle(), + cancelTitle ?? "取消", + style: this.themeData!.cancelStyle.generateTextStyle(), ), ), ), diff --git a/lib/src/components/actionsheet/brn_selected_list_action_sheet.dart b/lib/src/components/actionsheet/brn_selected_list_action_sheet.dart index d2c7bf0e..de888a0d 100644 --- a/lib/src/components/actionsheet/brn_selected_list_action_sheet.dart +++ b/lib/src/components/actionsheet/brn_selected_list_action_sheet.dart @@ -1,5 +1,3 @@ -// @dart=2.9 - import 'dart:math'; import 'dart:ui'; @@ -47,19 +45,16 @@ class BrnSelectedListActionSheetController extends ChangeNotifier { /// 自动与 globalKey 绑定的组件左右对齐,并从其顶部弹出。clear /// 2. 外界需要自己监听 Android 上的系统返回事件,并且调用组件的 [dismiss] 方法!否则,组件不能正常关闭。 class BrnSelectedListActionSheet { - @required - final BuildContext context; + final BuildContext? context; /// 数据源列表 - @required - final List items; + final List? items; /// 获取对应 index 行内容的回调。类型必须为 String 或者自定义的 widget.自定义 widget 时,左边的 icon 会自动隐藏,自定义widget填充整行。 - @required - final dynamic Function(int index, T entity) itemTitleBuilder; + final dynamic Function(int index, T entity)? itemTitleBuilder; /// 控制视图隐藏/刷新列表等方法 - final BrnSelectedListActionSheetController controller; + final BrnSelectedListActionSheetController? controller; /// 视图的最大高度。默认值 290,列表的内容的高度=maxHeight-65 final double maxHeight; @@ -77,10 +72,10 @@ class BrnSelectedListActionSheet { /// fontWeight: FontWeight.w600, /// decoration: TextDecoration.none) /// ``` - final String title; + final String? title; /// 自定义标题视图。默认外层有 `const EdgeInsets.fromLTRB(20, 20, 20, 15)` 的 padding,且优先级比 [title] 高 - final Widget titleWidget; + final Widget? titleWidget; /// 清空按钮是否显示,默认为 false final bool isClearButtonHidden; @@ -89,33 +84,33 @@ class BrnSelectedListActionSheet { final bool isDeleteButtonHidden; /// 每一行前边的 icon,可不传。如果该 image 没有设置,并且 itemTitleBuilder 返回的是自定义 widget,则该 widget 自动填充整行区域 - final Image itemIconImage; + final Image? itemIconImage; /// 点击清空按钮后的回调,如果没有实现该回调,则会显示默认弹窗。如果要关闭已选列表,请调用 dismiss()。 - final VoidCallback onClear; + final VoidCallback? onClear; /// 清空按钮点击显示默认确认弹窗之后,`确定` 按钮的点击回调 - final VoidCallback onClearConfirmed; + final VoidCallback? onClearConfirmed; /// 清空按钮点击显示默认确认弹窗之后,`取消` 按钮的点击回调 - final VoidCallback onClearCanceled; + final VoidCallback? onClearCanceled; /// 每一行删除按钮的点击回调。返回值:是否要删除该 entity,如果该 handler 没有实现或者返回 true,则删除 - final bool Function(int deleteIdx, T deleteEntity) onItemDelete; + final bool Function(int deleteIdx, T deleteEntity)? onItemDelete; /// 视图显示时的回调 - final VoidCallback onListShowed; + final VoidCallback? onListShowed; /// 视图隐藏时的回调,会把是否是清空按钮触发的销毁视图回传 - final void Function(bool isClosedByClearButton) onListDismissed; + final void Function(bool isClosedByClearButton)? onListDismissed; - OverlayEntry _overlayEntry; - double _leftOffset; + OverlayEntry? _overlayEntry; + double? _leftOffset; double _bottomKeyOffset = 0; - double _maxWidth; + double? _maxWidth; BrnSelectedListActionSheet( - {this.context, + {required this.context, this.maxHeight = 290, this.bottomOffset = 82, this.title, @@ -123,8 +118,8 @@ class BrnSelectedListActionSheet { this.isClearButtonHidden = false, this.isDeleteButtonHidden = false, this.itemIconImage, - this.items, - this.itemTitleBuilder, + required this.items, + required this.itemTitleBuilder, this.onClear, this.onClearConfirmed, this.onClearCanceled, @@ -135,22 +130,23 @@ class BrnSelectedListActionSheet { void _dismissHandler(bool isClear) { if (onListDismissed != null) { - onListDismissed(isClear); + onListDismissed!(isClear); } if (_overlayEntry != null) { - _overlayEntry.remove(); + _overlayEntry!.remove(); _overlayEntry = null; } } /// bottomWidgetKey: 已选列表下边操作区域绑定的 GlobalKey,已选列表会自动与操作区域左右对齐,且从操作区域的顶部滑出 - void showWithTargetKey({GlobalKey bottomWidgetKey}) { + void showWithTargetKey({required GlobalKey? bottomWidgetKey}) { assert(bottomWidgetKey != null); - RenderBox renderBox = bottomWidgetKey?.currentContext?.findRenderObject(); + RenderBox? renderBox = + bottomWidgetKey?.currentContext?.findRenderObject() as RenderBox?; var offset = renderBox?.localToGlobal(Offset.zero); _leftOffset = offset?.dx ?? 0; - _maxWidth = renderBox?.size?.width ?? MediaQuery.of(context).size.width; - _bottomKeyOffset = MediaQuery.of(context).size.height - (offset?.dy ?? 0); + _maxWidth = renderBox?.size.width ?? MediaQuery.of(context!).size.width; + _bottomKeyOffset = MediaQuery.of(context!).size.height - (offset?.dy ?? 0); this._innerShow(true); } @@ -162,7 +158,7 @@ class BrnSelectedListActionSheet { if (_overlayEntry != null) { return; } - BrnSelectedListActionSheetController tempCcontroller = controller; + BrnSelectedListActionSheetController? tempCcontroller = controller; if (tempCcontroller == null) { tempCcontroller = BrnSelectedListActionSheetController(); tempCcontroller._isHidden = false; @@ -177,7 +173,7 @@ class BrnSelectedListActionSheet { onItemDelete: this.onItemDelete, controller: tempCcontroller, ); - content._overlayState = Overlay.of(context); + content._overlayState = Overlay.of(context!); OverlayEntry overlayEntry = OverlayEntry(builder: (context) { if (_maxWidth == null) { _maxWidth = MediaQuery.of(context).size.width; @@ -188,7 +184,7 @@ class BrnSelectedListActionSheet { return Positioned( top: MediaQuery.of(context).viewInsets.top, left: _leftOffset, - bottom: (showByKey ?? false) + bottom: (showByKey) ? _bottomKeyOffset : (bottomOffset + MediaQuery.of(context).padding.bottom + @@ -198,32 +194,32 @@ class BrnSelectedListActionSheet { child: content, )); }); - content._overlayState.insert(overlayEntry); + content._overlayState!.insert(overlayEntry); _overlayEntry = overlayEntry; if (onListShowed != null) { - onListShowed(); + onListShowed!(); } } } // ignore: must_be_immutable class _BrnActionSheetSelectedItemListContentWidget extends StatefulWidget { - final BrnSelectedListActionSheet itemWidget; - final void Function(bool isClear) onDismiss; - final dynamic Function(int index, T entity) itemTitleBuilder; - final bool Function(int deleteIdx, T deleteEntity) onItemDelete; - final BrnSelectedListActionSheetController controller; + final BrnSelectedListActionSheet? itemWidget; + final void Function(bool isClear)? onDismiss; + final dynamic Function(int index, T entity)? itemTitleBuilder; + final bool Function(int deleteIdx, T deleteEntity)? onItemDelete; + final BrnSelectedListActionSheetController? controller; - OverlayState _overlayState; + OverlayState? _overlayState; // 位置动画 - Animation _yAnimation; + late Animation _yAnimation; // 背景透明度动画 - Animation _alphaAnimation; - AnimationController _yAnimationController; - AnimationController _alphaAnimationController; + late Animation _alphaAnimation; + late AnimationController _yAnimationController; + late AnimationController _alphaAnimationController; _BrnActionSheetSelectedItemListContentWidget( {this.itemWidget, @@ -247,10 +243,10 @@ class _BrnActionSheetSelectedItemListContentWidget extends StatefulWidget { } class _BrnActionSheetSelectedItemListState - extends State<_BrnActionSheetSelectedItemListContentWidget> + extends State<_BrnActionSheetSelectedItemListContentWidget> with TickerProviderStateMixin { bool _isClosedByClear = false; - BrnSelectedListActionSheetController _controller; + BrnSelectedListActionSheetController? _controller; @override initState() { @@ -265,26 +261,22 @@ class _BrnActionSheetSelectedItemListState @override dispose() { //路由销毁时需要释放动画资源 - if (widget._yAnimationController != null) { - widget._yAnimationController.dispose(); - } - if (widget._alphaAnimationController != null) { - widget._alphaAnimationController.dispose(); - } + widget._yAnimationController.dispose(); + widget._alphaAnimationController.dispose(); _controller?.removeListener(_onListenHandler); _controller = null; super.dispose(); } void _onListenHandler() { - if (_controller.isShouldReloadData) { + if (_controller!.isShouldReloadData) { if (mounted) { setState(() {}); } - _controller.isShouldReloadData = false; - } else if (_controller.isSelectedListDismissed) { + _controller!.isShouldReloadData = false; + } else if (_controller!.isSelectedListDismissed) { widget.dismissWithAnimation(); - _controller.isSelectedListDismissed = false; + _controller!.isSelectedListDismissed = false; } } @@ -302,14 +294,14 @@ class _BrnActionSheetSelectedItemListState }) ..addStatusListener((status) { if (status == AnimationStatus.dismissed) { - widget.onDismiss(_isClosedByClear); + widget.onDismiss!(_isClosedByClear); } }); - widget._yAnimation = yAnimation; + widget._yAnimation = yAnimation as Animation; Animation alphaAnimation = Tween(begin: 0.0, end: 0.7) .animate(alphaAnimationController) ..addListener(() {}); - widget._alphaAnimation = alphaAnimation; + widget._alphaAnimation = alphaAnimation as Animation; yAnimationController.forward(); alphaAnimationController.forward(); } @@ -320,47 +312,47 @@ class _BrnActionSheetSelectedItemListState } double getContentHeight() { - return widget.itemWidget.maxHeight; + return widget.itemWidget!.maxHeight; } void onClearAction() { - if (widget.itemWidget.onClear == null) { + if (widget.itemWidget!.onClear == null) { // 如果没有实现 onClear,执行默认弹窗并删除的逻辑 this.dismissContent(true); BrnDialogManager.showConfirmDialog(context, title: "确定要清空已选列表吗?", cancel: '取消', confirm: '确定', onConfirm: () { - if (widget.itemWidget.onClearConfirmed != null) { - widget.itemWidget.onClearConfirmed(); + if (widget.itemWidget!.onClearConfirmed != null) { + widget.itemWidget!.onClearConfirmed!(); } - if (widget.itemWidget.items != null) { - widget.itemWidget.items - .removeRange(0, widget.itemWidget.items.length); + if (widget.itemWidget!.items != null) { + widget.itemWidget!.items! + .removeRange(0, widget.itemWidget!.items!.length); } }, onCancel: () { - if (widget.itemWidget.onClearCanceled != null) { - widget.itemWidget.onClearCanceled(); + if (widget.itemWidget!.onClearCanceled != null) { + widget.itemWidget!.onClearCanceled!(); } }); } else { - widget.itemWidget.onClear(); + widget.itemWidget!.onClear!(); } } void onDeleteItemAction(int idx) { - if (widget.itemWidget.items == null || - idx >= widget.itemWidget.items.length) { + if (widget.itemWidget!.items == null || + idx >= widget.itemWidget!.items!.length) { debugPrint( - 'idx:$idx out of range of selectedModelList:${widget.itemWidget.items.length}!!!'); + 'idx:$idx out of range of selectedModelList:${widget.itemWidget!.items!.length}!!!'); return; } bool shouldDelete = true; if (widget.onItemDelete != null) { - shouldDelete = widget.onItemDelete(idx, widget.itemWidget.items[idx]); + shouldDelete = widget.onItemDelete!(idx, widget.itemWidget!.items![idx]); } if (shouldDelete) { setState(() { - widget.itemWidget.items.remove(widget.itemWidget.items[idx]); + widget.itemWidget!.items!.remove(widget.itemWidget!.items![idx]); }); } } @@ -368,10 +360,10 @@ class _BrnActionSheetSelectedItemListState @override Widget build(BuildContext context) { // 顶部标题处理 - String title = - (widget.itemWidget.title != null && widget.itemWidget.title.length > 0) - ? widget.itemWidget.title - : '已选列表'; + String? title = (widget.itemWidget!.title != null && + widget.itemWidget!.title!.length > 0) + ? widget.itemWidget!.title + : '已选列表'; TextStyle titleStyle = const TextStyle( fontSize: 18, color: Color(0xff222222), @@ -380,16 +372,15 @@ class _BrnActionSheetSelectedItemListState Widget topTitle = Expanded( child: Padding( padding: const EdgeInsets.fromLTRB(20, 20, 20, 15), - child: widget.itemWidget.titleWidget ?? + child: widget.itemWidget!.titleWidget ?? Text( - title, + title!, style: titleStyle, ), )); - List topWidgetList = List(); + List topWidgetList = []; topWidgetList.add(topTitle); - if (widget.itemWidget.isClearButtonHidden != null && - !widget.itemWidget.isClearButtonHidden) { + if (!widget.itemWidget!.isClearButtonHidden) { Widget clearWidget = GestureDetector( onTap: () { this.onClearAction(); @@ -409,13 +400,13 @@ class _BrnActionSheetSelectedItemListState // 每一行 item 前的 icon Widget itemIcon; - if (widget.itemWidget.itemIconImage != null) { + if (widget.itemWidget!.itemIconImage != null) { itemIcon = Container( color: Colors.white, height: 50, width: 45, padding: const EdgeInsets.only(left: 20, right: 8), - child: widget.itemWidget.itemIconImage); + child: widget.itemWidget!.itemIconImage); } else { itemIcon = Container(color: Colors.white, width: 20); } @@ -458,18 +449,18 @@ class _BrnActionSheetSelectedItemListState Expanded( child: ListView.builder( padding: EdgeInsets.zero, - itemCount: widget.itemWidget.items != null - ? widget.itemWidget.items.length + itemCount: widget.itemWidget!.items != null + ? widget.itemWidget!.items!.length : 0, itemBuilder: (BuildContext context, int index) { // 是否展示左侧的图标 bool shouldHideIcon = false; // 获取标题 Widget content = Container(color: Colors.white); - if (widget.itemWidget.items != null && - index < widget.itemWidget.items.length) { - var item = widget.itemTitleBuilder( - index, widget.itemWidget.items[index]); + if (widget.itemWidget!.items != null && + index < widget.itemWidget!.items!.length) { + var item = widget.itemTitleBuilder!( + index, widget.itemWidget!.items![index]); if (item is String) { content = Text( item, @@ -502,7 +493,7 @@ class _BrnActionSheetSelectedItemListState ), Offstage( offstage: widget - .itemWidget.isDeleteButtonHidden, + .itemWidget!.isDeleteButtonHidden, child: GestureDetector( onTap: () { this.onDeleteItemAction(index); diff --git a/lib/src/components/actionsheet/brn_share_action_sheet.dart b/lib/src/components/actionsheet/brn_share_action_sheet.dart index bf18f5f9..6cfc6e62 100644 --- a/lib/src/components/actionsheet/brn_share_action_sheet.dart +++ b/lib/src/components/actionsheet/brn_share_action_sheet.dart @@ -1,5 +1,3 @@ -// @dart=2.9 - import 'package:bruno/src/components/line/brn_line.dart'; import 'package:bruno/src/constants/brn_constants.dart'; import 'package:bruno/src/theme/brn_theme_configurator.dart'; @@ -21,10 +19,10 @@ class BrnShareItem extends Object { int shareType; /// 自定义标题 - String customTitle; + String? customTitle; /// 自定义图标 - Widget customImage; + Widget? customImage; /// 是否可点击(如果为预设类型,设置为不可点击后会变为相应的置灰图标)默认为true bool canClick; @@ -40,16 +38,16 @@ class BrnShareItem extends Object { // ignore: must_be_immutable class BrnShareActionSheet extends StatelessWidget { /// 第一行渠道列表 - final List firstShareChannels; + final List? firstShareChannels; /// 第二行渠道列表 - final List secondShareChannels; + final List? secondShareChannels; /// 列表标题 - final String mainTitle; + final String? mainTitle; /// 取消按钮名称 - final String cancelTitle; + final String? cancelTitle; /// 取消按钮的文本颜色,默认值为 Color(0xff222222) final Color textColor; @@ -58,10 +56,10 @@ class BrnShareActionSheet extends StatelessWidget { final Color shareTextColor; /// 点击事件回调 - final BrnShareActionSheetItemClickCallBack clickCallBack; + final BrnShareActionSheetItemClickCallBack? clickCallBack; /// 点击事件拦截回调(如果配置了此项,返回值为是否拦截,如果为true,则进行拦截,不进行默认回调) - final BrnShareActionSheetOnItemClickInterceptor clickInterceptor; + final BrnShareActionSheetOnItemClickInterceptor? clickInterceptor; BrnShareActionSheet({ this.firstShareChannels, @@ -99,13 +97,13 @@ class BrnShareActionSheet extends StatelessWidget { } /// 构建单个分享渠道 - Widget _configChannelWidget(BuildContext context, int section, int index) { + Widget? _configChannelWidget(BuildContext context, int section, int index) { // 分享类型 BrnShareItem channel; // 渠道名称 - String title; + String? title; // 图片 - Widget image; + Widget? image; // 元素宽度(图片边长也是48) double itemsWidth = 48; // 元素间隔为20写死 @@ -114,9 +112,9 @@ class BrnShareActionSheet extends StatelessWidget { image = null; // 判断区域 if (section == 0) { - channel = firstShareChannels[index]; + channel = firstShareChannels![index]; } else { - channel = secondShareChannels[index]; + channel = secondShareChannels![index]; } // 判断是否为自定义标题 title = (channel.shareType == BrnShareItemConstants.shareCustom) @@ -131,7 +129,7 @@ class BrnShareActionSheet extends StatelessWidget { : BrunoTools.getAssetImage(BrnShareItemConstants .disableShareItemImagePathList[channel.shareType])); //如果没图或没文字则不显示 - if (title == null || image == null) { + if (image == null) { return null; } @@ -162,10 +160,10 @@ class BrnShareActionSheet extends StatelessWidget { ), onTap: () { if (clickInterceptor == null || - !clickInterceptor(section, index, channel)) { + !clickInterceptor!(section, index, channel)) { // 推荐使用回调方法处理点击事件!!!!!!!!!! if (clickCallBack != null && channel.canClick) { - clickCallBack(section, index, channel); + clickCallBack!(section, index, channel); // 如果未拦截并且可点击,则pop掉当前页面 Navigator.of(context).pop(); } @@ -176,11 +174,11 @@ class BrnShareActionSheet extends StatelessWidget { /// 构建actionSheet的按钮 Widget _configActionWidgets(BuildContext context) { - List tiles = List(); + List tiles = []; // 预设分享渠道 - List firstSectionItems = List(); + List firstSectionItems = []; // 自定义分享渠道 - List secondSectionItems = List(); + List secondSectionItems = []; // 容器左侧留白 double leftGap = 10; // 容器上方留白 @@ -189,8 +187,8 @@ class BrnShareActionSheet extends StatelessWidget { double bottomGap = 20; // 构建第一行 if (firstShareChannels != null) { - for (int index = 0; index < firstShareChannels.length; index++) { - Widget item = _configChannelWidget(context, 0, index); + for (int index = 0; index < firstShareChannels!.length; index++) { + Widget? item = _configChannelWidget(context, 0, index); if (item != null) { firstSectionItems.add(item); } @@ -198,8 +196,8 @@ class BrnShareActionSheet extends StatelessWidget { } // 构建第二行 if (secondShareChannels != null) { - for (int index = 0; index < secondShareChannels.length; index++) { - Widget item = _configChannelWidget(context, 1, index); + for (int index = 0; index < secondShareChannels!.length; index++) { + Widget? item = _configChannelWidget(context, 1, index); if (item != null) { secondSectionItems.add(item); } @@ -270,7 +268,7 @@ class BrnShareActionSheet extends StatelessWidget { padding: EdgeInsets.only(left: 61, right: 61, top: 12, bottom: 12), child: Center( child: Text( - (cancelTitle != null) ? cancelTitle : "取消", + cancelTitle ?? "取消", style: TextStyle( fontSize: 16, fontWeight: FontWeight.w600, color: textColor), ), From 7a856534c5db79b05767fbedb573e0655c1b8fd7 Mon Sep 17 00:00:00 2001 From: yuanjunliang Date: Wed, 19 Jan 2022 09:42:02 +0800 Subject: [PATCH 2/2] sheet: code review --- .../brn_selected_list_action_sheet.dart | 78 +++++++++---------- 1 file changed, 35 insertions(+), 43 deletions(-) diff --git a/lib/src/components/actionsheet/brn_selected_list_action_sheet.dart b/lib/src/components/actionsheet/brn_selected_list_action_sheet.dart index de888a0d..606aefbc 100644 --- a/lib/src/components/actionsheet/brn_selected_list_action_sheet.dart +++ b/lib/src/components/actionsheet/brn_selected_list_action_sheet.dart @@ -45,13 +45,13 @@ class BrnSelectedListActionSheetController extends ChangeNotifier { /// 自动与 globalKey 绑定的组件左右对齐,并从其顶部弹出。clear /// 2. 外界需要自己监听 Android 上的系统返回事件,并且调用组件的 [dismiss] 方法!否则,组件不能正常关闭。 class BrnSelectedListActionSheet { - final BuildContext? context; + final BuildContext context; /// 数据源列表 - final List? items; + final List items; /// 获取对应 index 行内容的回调。类型必须为 String 或者自定义的 widget.自定义 widget 时,左边的 icon 会自动隐藏,自定义widget填充整行。 - final dynamic Function(int index, T entity)? itemTitleBuilder; + final dynamic Function(int index, T entity) itemTitleBuilder; /// 控制视图隐藏/刷新列表等方法 final BrnSelectedListActionSheetController? controller; @@ -139,14 +139,13 @@ class BrnSelectedListActionSheet { } /// bottomWidgetKey: 已选列表下边操作区域绑定的 GlobalKey,已选列表会自动与操作区域左右对齐,且从操作区域的顶部滑出 - void showWithTargetKey({required GlobalKey? bottomWidgetKey}) { - assert(bottomWidgetKey != null); + void showWithTargetKey({required GlobalKey bottomWidgetKey}) { RenderBox? renderBox = - bottomWidgetKey?.currentContext?.findRenderObject() as RenderBox?; + bottomWidgetKey.currentContext?.findRenderObject() as RenderBox?; var offset = renderBox?.localToGlobal(Offset.zero); _leftOffset = offset?.dx ?? 0; - _maxWidth = renderBox?.size.width ?? MediaQuery.of(context!).size.width; - _bottomKeyOffset = MediaQuery.of(context!).size.height - (offset?.dy ?? 0); + _maxWidth = renderBox?.size.width ?? MediaQuery.of(context).size.width; + _bottomKeyOffset = MediaQuery.of(context).size.height - (offset?.dy ?? 0); this._innerShow(true); } @@ -173,7 +172,7 @@ class BrnSelectedListActionSheet { onItemDelete: this.onItemDelete, controller: tempCcontroller, ); - content._overlayState = Overlay.of(context!); + content._overlayState = Overlay.of(context); OverlayEntry overlayEntry = OverlayEntry(builder: (context) { if (_maxWidth == null) { _maxWidth = MediaQuery.of(context).size.width; @@ -205,7 +204,7 @@ class BrnSelectedListActionSheet { // ignore: must_be_immutable class _BrnActionSheetSelectedItemListContentWidget extends StatefulWidget { - final BrnSelectedListActionSheet? itemWidget; + final BrnSelectedListActionSheet itemWidget; final void Function(bool isClear)? onDismiss; final dynamic Function(int index, T entity)? itemTitleBuilder; final bool Function(int deleteIdx, T deleteEntity)? onItemDelete; @@ -222,7 +221,7 @@ class _BrnActionSheetSelectedItemListContentWidget extends StatefulWidget { late AnimationController _alphaAnimationController; _BrnActionSheetSelectedItemListContentWidget( - {this.itemWidget, + {required this.itemWidget, this.onDismiss, this.itemTitleBuilder, this.onItemDelete, @@ -312,47 +311,43 @@ class _BrnActionSheetSelectedItemListState } double getContentHeight() { - return widget.itemWidget!.maxHeight; + return widget.itemWidget.maxHeight; } void onClearAction() { - if (widget.itemWidget!.onClear == null) { + if (widget.itemWidget.onClear == null) { // 如果没有实现 onClear,执行默认弹窗并删除的逻辑 this.dismissContent(true); BrnDialogManager.showConfirmDialog(context, title: "确定要清空已选列表吗?", cancel: '取消', confirm: '确定', onConfirm: () { - if (widget.itemWidget!.onClearConfirmed != null) { - widget.itemWidget!.onClearConfirmed!(); - } - if (widget.itemWidget!.items != null) { - widget.itemWidget!.items! - .removeRange(0, widget.itemWidget!.items!.length); + if (widget.itemWidget.onClearConfirmed != null) { + widget.itemWidget.onClearConfirmed!(); } + widget.itemWidget.items.removeRange(0, widget.itemWidget.items.length); }, onCancel: () { - if (widget.itemWidget!.onClearCanceled != null) { - widget.itemWidget!.onClearCanceled!(); + if (widget.itemWidget.onClearCanceled != null) { + widget.itemWidget.onClearCanceled!(); } }); } else { - widget.itemWidget!.onClear!(); + widget.itemWidget.onClear!(); } } void onDeleteItemAction(int idx) { - if (widget.itemWidget!.items == null || - idx >= widget.itemWidget!.items!.length) { + if (idx >= widget.itemWidget.items.length) { debugPrint( - 'idx:$idx out of range of selectedModelList:${widget.itemWidget!.items!.length}!!!'); + 'idx:$idx out of range of selectedModelList:${widget.itemWidget.items.length}!!!'); return; } bool shouldDelete = true; if (widget.onItemDelete != null) { - shouldDelete = widget.onItemDelete!(idx, widget.itemWidget!.items![idx]); + shouldDelete = widget.onItemDelete!(idx, widget.itemWidget.items[idx]); } if (shouldDelete) { setState(() { - widget.itemWidget!.items!.remove(widget.itemWidget!.items![idx]); + widget.itemWidget.items.remove(widget.itemWidget.items[idx]); }); } } @@ -360,10 +355,10 @@ class _BrnActionSheetSelectedItemListState @override Widget build(BuildContext context) { // 顶部标题处理 - String? title = (widget.itemWidget!.title != null && - widget.itemWidget!.title!.length > 0) - ? widget.itemWidget!.title - : '已选列表'; + String title = + (widget.itemWidget.title != null && widget.itemWidget.title!.length > 0) + ? widget.itemWidget.title! + : '已选列表'; TextStyle titleStyle = const TextStyle( fontSize: 18, color: Color(0xff222222), @@ -372,15 +367,15 @@ class _BrnActionSheetSelectedItemListState Widget topTitle = Expanded( child: Padding( padding: const EdgeInsets.fromLTRB(20, 20, 20, 15), - child: widget.itemWidget!.titleWidget ?? + child: widget.itemWidget.titleWidget ?? Text( - title!, + title, style: titleStyle, ), )); List topWidgetList = []; topWidgetList.add(topTitle); - if (!widget.itemWidget!.isClearButtonHidden) { + if (!widget.itemWidget.isClearButtonHidden) { Widget clearWidget = GestureDetector( onTap: () { this.onClearAction(); @@ -400,13 +395,13 @@ class _BrnActionSheetSelectedItemListState // 每一行 item 前的 icon Widget itemIcon; - if (widget.itemWidget!.itemIconImage != null) { + if (widget.itemWidget.itemIconImage != null) { itemIcon = Container( color: Colors.white, height: 50, width: 45, padding: const EdgeInsets.only(left: 20, right: 8), - child: widget.itemWidget!.itemIconImage); + child: widget.itemWidget.itemIconImage); } else { itemIcon = Container(color: Colors.white, width: 20); } @@ -449,18 +444,15 @@ class _BrnActionSheetSelectedItemListState Expanded( child: ListView.builder( padding: EdgeInsets.zero, - itemCount: widget.itemWidget!.items != null - ? widget.itemWidget!.items!.length - : 0, + itemCount: widget.itemWidget.items.length, itemBuilder: (BuildContext context, int index) { // 是否展示左侧的图标 bool shouldHideIcon = false; // 获取标题 Widget content = Container(color: Colors.white); - if (widget.itemWidget!.items != null && - index < widget.itemWidget!.items!.length) { + if (index < widget.itemWidget.items.length) { var item = widget.itemTitleBuilder!( - index, widget.itemWidget!.items![index]); + index, widget.itemWidget.items[index]); if (item is String) { content = Text( item, @@ -493,7 +485,7 @@ class _BrnActionSheetSelectedItemListState ), Offstage( offstage: widget - .itemWidget!.isDeleteButtonHidden, + .itemWidget.isDeleteButtonHidden, child: GestureDetector( onTap: () { this.onDeleteItemAction(index);