diff --git a/lib/src/components/input/brn_input_text.dart b/lib/src/components/input/brn_input_text.dart index 79b9e387..8642af4b 100644 --- a/lib/src/components/input/brn_input_text.dart +++ b/lib/src/components/input/brn_input_text.dart @@ -1,5 +1,3 @@ -// @dart=2.9 - import 'package:bruno/src/theme/brn_theme_configurator.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; @@ -21,10 +19,10 @@ typedef BrnInputTextEditingCompleteCallback = Function(String input); class BrnInputText extends StatelessWidget { /// 搜索框输入内容改变时候的回调函数 - final BrnInputTextChangeCallback onTextChange; + final BrnInputTextChangeCallback? onTextChange; /// 点击确定后的回调 - final BrnInputTextSubmitCallback onSubmit; + final BrnInputTextSubmitCallback? onSubmit; /// 容器的最大高度,默认 200 final double maxHeight; @@ -39,10 +37,11 @@ class BrnInputText extends StatelessWidget { final String hint; /// 输入框的初始值,默认为"" + /// 不能定义为String,兼容example调用的传值 final String textString; /// 用于对 TextField 更精细的控制,若传入该字段,[textString] 参数将失效,可使用 TextEditingController.text 进行赋值。 - final TextEditingController textEditingController; + final TextEditingController? textEditingController; /// 最大字数,默认200 final int maxLength; @@ -54,22 +53,22 @@ class BrnInputText extends StatelessWidget { final EdgeInsetsGeometry padding; /// 最大hint行数 - final int maxHintLines; + final int? maxHintLines; /// 搜索框的焦点控制器 - final FocusNode focusNode; + final FocusNode? focusNode; /// 键盘输入行为, 默认为 TextInputAction.done final TextInputAction textInputAction; /// 光标展示 - final bool autoFocus; + final bool? autoFocus; /// 背景圆角 - final double borderRadius; + final double? borderRadius; /// 边框颜色 - final Color borderColor; + final Color? borderColor; BrnInputText({ this.onTextChange, @@ -98,13 +97,13 @@ class BrnInputText extends StatelessWidget { Widget _inputText(BuildContext context) { String textData = textString; - if (textData != null && textString.runes.length > maxLength) { + if (textString.runes.length > maxLength) { var sRunes = textData.runes; textData = String.fromCharCodes(sRunes, 0, maxLength); } var _controller = textEditingController; if (_controller == null) { - if (textData != null && textData.length > 0) { + if (textData.isNotEmpty) { _controller = TextEditingController.fromValue(TextEditingValue( text: textData, selection: TextSelection.fromPosition(TextPosition( @@ -130,7 +129,7 @@ class BrnInputText extends StatelessWidget { controller: _controller, keyboardType: TextInputType.multiline, maxLength: maxLength, - maxLengthEnforced: true, + maxLengthEnforcement: MaxLengthEnforcement.enforced, maxLines: null, autofocus: autoFocus ?? true, focusNode: focusNode, @@ -143,8 +142,12 @@ class BrnInputText extends StatelessWidget { .getConfig() .commonConfig .colorTextBase), - buildCounter: (BuildContext context, - {int currentLength, int maxLength, bool isFocused}) { + buildCounter: ( + BuildContext context, { + required int currentLength, + required int? maxLength, + required bool isFocused, + }) { return Row( mainAxisAlignment: MainAxisAlignment.end, children: [ @@ -184,12 +187,13 @@ class BrnInputText extends StatelessWidget { ), onSubmitted: (text) { if (onSubmit != null) { - onSubmit(text); + onSubmit!(text); } }, + onChanged: (text) { if (onTextChange != null) { - onTextChange(text); + onTextChange!(text); } }, ), diff --git a/lib/src/components/navbar/brn_appbar.dart b/lib/src/components/navbar/brn_appbar.dart index 23e426c6..93ee65b5 100644 --- a/lib/src/components/navbar/brn_appbar.dart +++ b/lib/src/components/navbar/brn_appbar.dart @@ -1,5 +1,3 @@ -// @dart=2.9 - import 'dart:ui'; import 'package:bruno/src/components/line/brn_line.dart'; @@ -7,7 +5,6 @@ import 'package:bruno/src/theme/brn_theme_configurator.dart'; import 'package:bruno/src/theme/configs/brn_appbar_config.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -import 'package:flutter/widgets.dart'; /// AppBar组件,基于[AppBar]封装。为了解决原生的AppBar对Leading宽度的限制 /// 在1.21版本之后,Flutter放开了宽度的限制[https://github.com/flutter/flutter/blob/flutter-1.21-candidate.0/packages/flutter/lib/src/material/app_bar.dart] @@ -99,7 +96,7 @@ import 'package:flutter/widgets.dart'; class BrnAppBar extends PreferredSize { /// 导航栏左侧活动区域,在为null且 /// [automaticallyImplyLeading]为true时默认赋值为[BrnBackLeading] - final Widget leading; + final Widget? leading; /// AppBar标题,必须是String或者Widget类型 /// 为String时,会使用[BrnAppBarTitle]来加载title @@ -115,43 +112,43 @@ class BrnAppBar extends PreferredSize { /// 以下属性都对应于[AppBar]中的属性 /// 详细介绍可以查阅[AppBar]的文档 - final Color backgroundColor; - final PreferredSizeWidget bottom; + final Color? backgroundColor; + final PreferredSizeWidget? bottom; final double elevation; - final Brightness brightness; + final Brightness? brightness; final double toolbarOpacity; final double bottomOpacity; final Alignment titleAlignment; - final Widget flexibleSpace; - final double leadingWidth; - final Color shadowColor; - final ShapeBorder shape; - final IconThemeData iconTheme; - final IconThemeData actionsIconTheme; - final TextTheme textTheme; + final Widget? flexibleSpace; + final double? leadingWidth; + final Color? shadowColor; + final ShapeBorder? shape; + final IconThemeData? iconTheme; + final IconThemeData? actionsIconTheme; + final TextTheme? textTheme; final bool primary; final bool excludeHeaderSemantics; - final double titleSpacing; + final double? titleSpacing; /// 默认处理了返回按钮,flutter的pop,如果是native打开的话,可能需要单独处理,否则会出现白屏 /// backLeadCallback是默认的处理回调 /// DefaultLeadingCallBack 也可以通过改方法参数 设置统一的返回处理,该参数是静态的 - final VoidCallback backLeadCallback; + final VoidCallback? backLeadCallback; /// 是否显示默认的eeeeee分割线,默认显示,可以设置为不显示 final bool showDefaultBottom; final bool showLeadingDivider; - final BrnAppBarConfig themeData; + final BrnAppBarConfig? themeData; BrnAppBar( - {Key key, + {Key? key, this.leading, this.showLeadingDivider = false, this.title, this.actions, this.backgroundColor, this.bottom, - this.elevation, + this.elevation = 0, this.automaticallyImplyLeading = true, this.brightness, this.toolbarOpacity = 1.0, @@ -166,18 +163,18 @@ class BrnAppBar extends PreferredSize { this.shape, this.iconTheme, this.actionsIconTheme, - this.excludeHeaderSemantics, - this.primary, + this.excludeHeaderSemantics = false, + this.primary = true, this.textTheme, this.titleSpacing}) : assert( actions == null || actions is Widget || (actions is List)), assert(title == null || title is String || title is Widget), - super(key: key, child: null, preferredSize: null); + super(key: key, child: Container(), preferredSize: Size(0, 0)); BrnAppBar.buildSearchResultStyle( - {Key key, - String title, + {Key? key, + String? title, this.backgroundColor, this.bottom, this.brightness, @@ -191,8 +188,8 @@ class BrnAppBar extends PreferredSize { this.shape, this.iconTheme, this.actionsIconTheme, - this.excludeHeaderSemantics, - this.primary, + this.excludeHeaderSemantics = false, + this.primary = true, this.textTheme, this.titleSpacing}) : this.actions = null, @@ -213,7 +210,7 @@ class BrnAppBar extends PreferredSize { backLeadCallback: backLeadCallback, showDefaultBottom: showDefaultBottom, ), - super(key: key, child: null, preferredSize: null); + super(key: key, child: Container(), preferredSize: const Size(0, 0)); @override Size get preferredSize { @@ -223,7 +220,7 @@ class BrnAppBar extends PreferredSize { .appBarConfig .merge(_defaultConfig); return Size.fromHeight( - _defaultConfig.appBarHeight + (bottom?.preferredSize?.height ?? 0.0)); + _defaultConfig.appBarHeight + (bottom?.preferredSize.height ?? 0.0)); } @override @@ -243,13 +240,13 @@ class BrnAppBar extends PreferredSize { .appBarConfig .merge(_defaultConfig); - WidgetsBinding.instance.addPostFrameCallback((_) { + WidgetsBinding.instance?.addPostFrameCallback((_) { SystemChrome.setSystemUIOverlayStyle(_defaultConfig.systemUiOverlayStyle); }); return super.build(context); } - Widget _buildBarBottom() { + PreferredSizeWidget? _buildBarBottom() { if (brightness == null || brightness == Brightness.light) { if (bottom == null && showDefaultBottom) { return BrnBarBottomDivider(); @@ -275,12 +272,11 @@ class BrnAppBar extends PreferredSize { .appBarConfig .merge(_defaultConfig); - Widget flexibleSpace; + Widget? flexibleSpace; if (this.flexibleSpace != null) { flexibleSpace = Container( height: _defaultConfig.appBarHeight + - MediaQueryData.fromWindow(window)?.padding?.top ?? - 0, + MediaQueryData.fromWindow(window).padding.top, child: this.flexibleSpace, ); } @@ -293,28 +289,28 @@ class BrnAppBar extends PreferredSize { automaticallyImplyLeading: false, title: _buildAppBarTitle(_defaultConfig), centerTitle: true, - elevation: elevation ?? 0, + elevation: elevation, backgroundColor: _defaultConfig.backgroundColor, actions: _wrapActions(_defaultConfig), bottom: _buildBarBottom(), brightness: brightness ?? Brightness.light, - toolbarOpacity: toolbarOpacity ?? 1.0, - bottomOpacity: bottomOpacity ?? 1.0, + toolbarOpacity: toolbarOpacity, + bottomOpacity: bottomOpacity, flexibleSpace: flexibleSpace, shadowColor: shadowColor, shape: shape, iconTheme: iconTheme, actionsIconTheme: actionsIconTheme, textTheme: textTheme, - primary: primary ?? true, - excludeHeaderSemantics: excludeHeaderSemantics ?? false, + primary: primary, + excludeHeaderSemantics: excludeHeaderSemantics, ); } // 根据输入的leading 设置默认的leadingWidth double _culLeadingSize(BrnAppBarConfig themeData) { if (leadingWidth != null) { - return leadingWidth; + return leadingWidth!; } if (leading is BrnDoubleLeading) { return themeData.leftAndRightPadding + @@ -330,7 +326,7 @@ class BrnAppBar extends PreferredSize { // 对[actions]进行包装: 单一的Widget会添加右边距 // List在添加右边距的 并 添加action中的间距 - List _wrapActions(BrnAppBarConfig themeData) { + List? _wrapActions(BrnAppBarConfig themeData) { if (actions == null || !(actions is List || actions is Widget)) { return null; } @@ -340,9 +336,9 @@ class BrnAppBar extends PreferredSize { if (actions.isEmpty) { return actionList; } - List tmp = (actions as List)?.map((_) { + List tmp = (actions as List).map((_) { return (_ is BrnTextAction) ? _warpRealAction(_) : _; - })?.toList(); + }).toList(); for (int i = 0, n = tmp.length; i < n; i++) { actionList.add(tmp[i]); @@ -366,10 +362,10 @@ class BrnAppBar extends PreferredSize { } // 详情请参考_ToolbarLayout的布局方法 - Widget _buildAppBarTitle( + Widget? _buildAppBarTitle( BrnAppBarConfig themeData, ) { - Widget realTitle; + Widget? realTitle; if (title is Widget) { return title; } @@ -384,8 +380,8 @@ class BrnAppBar extends PreferredSize { } // 如果leading是BrnBackLeading 需要添加左边距 - Widget _wrapLeading(BrnAppBarConfig barConfig) { - Widget realLeading = leading; + Widget? _wrapLeading(BrnAppBarConfig barConfig) { + Widget? realLeading = leading; if (leading == null && automaticallyImplyLeading) { realLeading = BrnBackLeading( iconPressed: backLeadCallback, @@ -405,12 +401,12 @@ class BrnAppBar extends PreferredSize { /// [BrnAppBar]中leading的默认实现 /// 宽度范围是40 class BrnBackLeading extends StatelessWidget { - final Widget child; - final VoidCallback iconPressed; - final BrnAppBarConfig themeData; + final Widget? child; + final VoidCallback? iconPressed; + final BrnAppBarConfig? themeData; BrnBackLeading({ - Key key, + Key? key, this.iconPressed, this.child, this.themeData, @@ -455,9 +451,10 @@ class BrnBackLeading extends StatelessWidget { class BrnDoubleLeading extends StatelessWidget { final Widget first; final Widget second; - final BrnAppBarConfig themeData; + final BrnAppBarConfig? themeData; - BrnDoubleLeading({Key key, this.first, this.second, this.themeData}) + BrnDoubleLeading( + {Key? key, required this.first, required this.second, this.themeData}) : super(key: key); @override @@ -487,15 +484,15 @@ class BrnDoubleLeading extends StatelessWidget { /// 标题文字个数限制在8个以内,并且单行展示 class BrnAppBarTitle extends StatelessWidget { final String title; - final BrnAppBarConfig themeData; + final BrnAppBarConfig? themeData; - BrnAppBarTitle(this.title, {Key key, this.themeData}) : super(key: key); + BrnAppBarTitle(this.title, {Key? key, this.themeData}) : super(key: key); @override Widget build(BuildContext context) { BrnAppBarConfig _defaultThemeData = themeData ?? BrnAppBarConfig(); _defaultThemeData = BrnThemeConfigurator.instance - .getConfig(configId: themeData.configId) + .getConfig(configId: _defaultThemeData.configId) .appBarConfig .merge(this.themeData); @@ -506,7 +503,7 @@ class BrnAppBarTitle extends StatelessWidget { overflow: TextOverflow.ellipsis, ), constraints: BoxConstraints.loose(Size.fromWidth( - _defaultThemeData.titleStyle.generateTextStyle().fontSize * + (_defaultThemeData.titleStyle.generateTextStyle().fontSize ?? 18) * (_defaultThemeData.titleMaxLength + 1))), ); } @@ -517,17 +514,16 @@ class BrnAppBarTitle extends StatelessWidget { class BrnIconAction extends StatelessWidget { final Widget child; final VoidCallback iconPressed; - final double size; - final BrnAppBarConfig themeData; + final double? size; + final BrnAppBarConfig? themeData; BrnIconAction({ - Key key, - this.iconPressed, - this.child, + Key? key, + required this.iconPressed, + required this.child, this.size, this.themeData, - }) : assert(child != null && iconPressed != null), - super(key: key); + }) : super(key: key); @override Widget build(BuildContext context) { @@ -554,10 +550,10 @@ class BrnIconAction extends StatelessWidget { /// 此Widget中实现了大小约束,和点击实现,添加文本action时必须使用此类包裹 class BrnTextAction extends StatelessWidget { final String text; - final VoidCallback iconPressed; - final BrnAppBarConfig themeData; + final VoidCallback? iconPressed; + final BrnAppBarConfig? themeData; - BrnTextAction(this.text, {Key key, this.iconPressed, this.themeData}) + BrnTextAction(this.text, {Key? key, this.iconPressed, this.themeData}) : super(key: key); @override @@ -583,6 +579,9 @@ class BrnTextAction extends StatelessWidget { /// AppBar底部分割线,将实例传入[BrnAppBar.bottom]属性即可 class BrnBarBottomDivider extends PreferredSize { + BrnBarBottomDivider() + : super(child: Container(), preferredSize: const Size(0, 0)); + @override Size get preferredSize => Size.fromHeight(0.5); @@ -591,8 +590,8 @@ class BrnBarBottomDivider extends PreferredSize { } class _BrnSearchResultAppBar extends StatelessWidget { - final BrnAppBarConfig appBarConfig; - final String title; + final BrnAppBarConfig? appBarConfig; + final String? title; final backgroundColor; final bottom; final brightness; diff --git a/lib/src/components/navbar/brn_empty_appbar.dart b/lib/src/components/navbar/brn_empty_appbar.dart index 9e8a0793..5ec80181 100644 --- a/lib/src/components/navbar/brn_empty_appbar.dart +++ b/lib/src/components/navbar/brn_empty_appbar.dart @@ -1,13 +1,11 @@ -// @dart=2.9 - import 'package:flutter/material.dart'; -import 'package:flutter/widgets.dart'; class BrnEmptyAppBar extends PreferredSize { final double height; - final Color color; + final Color? color; - BrnEmptyAppBar(this.height, {this.color}); + BrnEmptyAppBar(this.height, {this.color}) + : super(child: Container(), preferredSize: const Size(0, 0)); @override Size get preferredSize => Size.fromHeight(height); diff --git a/lib/src/components/navbar/brn_search_bar.dart b/lib/src/components/navbar/brn_search_bar.dart index 4efe58a9..c83fbb9d 100644 --- a/lib/src/components/navbar/brn_search_bar.dart +++ b/lib/src/components/navbar/brn_search_bar.dart @@ -1,7 +1,3 @@ -// @dart=2.9 - -import 'dart:ui'; - import 'package:bruno/src/components/navbar/brn_appbar.dart'; import 'package:bruno/src/components/navbar/brn_appbar_theme.dart'; import 'package:bruno/src/constants/brn_asset_constants.dart'; @@ -37,37 +33,37 @@ typedef BrnSearchBarInputSubmitCallback = Function(String input); /// 更多信息 请查看[BrnAppBar] class BrnSearchAppbar extends PreferredSize { /// 搜索框的文本输入控制器 - final TextEditingController controller; + final TextEditingController? controller; /// 搜索框的焦点控制器 - final FocusNode focusNode; + final FocusNode? focusNode; /// 搜索框的左侧leading - final BrnSearchBarLeadClickCallback leadClickCallback; + final BrnSearchBarLeadClickCallback? leadClickCallback; /// 可以是字符串也可以是widget final dynamic leading; /// 取消点击的回调 - final BrnSearchBarDismissClickCallback dismissClickCallback; + final BrnSearchBarDismissClickCallback? dismissClickCallback; /// 输入变化的监听 - final BrnSearchBarInputChangeCallback searchBarInputChangeCallback; + final BrnSearchBarInputChangeCallback? searchBarInputChangeCallback; /// 输入框提交的监听 - final BrnSearchBarInputSubmitCallback searchBarInputSubmitCallback; + final BrnSearchBarInputSubmitCallback? searchBarInputSubmitCallback; /// 输入框的hint文字 - final String hint; + final String? hint; /// 输入框的hint的Style - final TextStyle hintStyle; + final TextStyle? hintStyle; /// 输入框的文本Style - final TextStyle inputTextStyle; + final TextStyle? inputTextStyle; /// 右侧取消的文本Style - final TextStyle dismissStyle; + final TextStyle? dismissStyle; /// 左侧的leading和搜索的分割线 final bool showDivider; @@ -79,7 +75,7 @@ class BrnSearchAppbar extends PreferredSize { final Brightness brightness; /// 清空回调 - final VoidCallback onClearTap; + final VoidCallback? onClearTap; const BrnSearchAppbar( {this.controller, @@ -96,7 +92,8 @@ class BrnSearchAppbar extends PreferredSize { this.autoFocus = true, this.brightness = Brightness.dark, this.onClearTap, - this.inputTextStyle}); + this.inputTextStyle}) + : super(child: const Center(), preferredSize: const Size(0, 0)); @override Widget get child => BrnAppBar( @@ -109,7 +106,7 @@ class BrnSearchAppbar extends PreferredSize { Size get preferredSize => Size.fromHeight(BrnAppBarTheme.appBarHeight); Widget build(BuildContext context) { - WidgetsBinding.instance.addPostFrameCallback((_) { + WidgetsBinding.instance?.addPostFrameCallback((_) { SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.light); }); return super.build(context); @@ -146,21 +143,21 @@ class BrnSearchAppbar extends PreferredSize { } class _SearchInputWidget extends StatefulWidget { - final FocusNode focusNode; - final TextEditingController textEditingController; - final BrnSearchBarLeadClickCallback leadClickCallback; - final BrnSearchBarDismissClickCallback dismissClickCallback; + final FocusNode? focusNode; + final TextEditingController? textEditingController; + final BrnSearchBarLeadClickCallback? leadClickCallback; + final BrnSearchBarDismissClickCallback? dismissClickCallback; final dynamic leading; - final BrnSearchBarInputChangeCallback searchBarInputChangeCallback; - final BrnSearchBarInputSubmitCallback searchBarInputSubmitCallback; - final String hint; - final TextStyle hintStyle; - final TextStyle inputTextStyle; - final TextStyle dismissStyle; + final BrnSearchBarInputChangeCallback? searchBarInputChangeCallback; + final BrnSearchBarInputSubmitCallback? searchBarInputSubmitCallback; + final String? hint; + final TextStyle? hintStyle; + final TextStyle? inputTextStyle; + final TextStyle? dismissStyle; final bool showDivider; final bool autoFocus; - final VoidCallback clearTapCallback; - final Brightness brightness; + final VoidCallback? clearTapCallback; + final Brightness? brightness; _SearchInputWidget( {this.focusNode, @@ -184,14 +181,14 @@ class _SearchInputWidget extends StatefulWidget { } class __SearchInputWidgetState extends State<_SearchInputWidget> { - FocusNode _focusNode; - ValueNotifier valueNotifier; - TextEditingController _controller; - Color _defaultInputTextColor; - Color _defaultCancelTextColor; - Color _defaultDividerColor; - Color _defaultHintTextColor; - Color _defaultClearIconColor; + late FocusNode _focusNode; + late ValueNotifier valueNotifier; + late TextEditingController _controller; + late Color _defaultInputTextColor; + late Color _defaultCancelTextColor; + late Color _defaultDividerColor; + late Color _defaultHintTextColor; + late Color _defaultClearIconColor; @override void initState() { @@ -228,7 +225,7 @@ class __SearchInputWidgetState extends State<_SearchInputWidget> { @override void dispose() { super.dispose(); - _focusNode?.removeListener(_handleFocusChangeListenerTick); + _focusNode.removeListener(_handleFocusChangeListenerTick); } void _handleFocusChangeListenerTick() { @@ -245,7 +242,7 @@ class __SearchInputWidgetState extends State<_SearchInputWidget> { GestureDetector( onTap: () { if (widget.leadClickCallback != null) { - widget.leadClickCallback(_controller, () { + widget.leadClickCallback!(_controller, () { setState(() {}); }); } @@ -317,14 +314,14 @@ class __SearchInputWidgetState extends State<_SearchInputWidget> { onChanged: (content) { valueNotifier.value = true; if (widget.searchBarInputChangeCallback != null) { - widget.searchBarInputChangeCallback(content); + widget.searchBarInputChangeCallback!(content); } setState(() {}); }, onSubmitted: (content) { valueNotifier.value = false; if (widget.searchBarInputSubmitCallback != null) { - widget.searchBarInputSubmitCallback(content); + widget.searchBarInputSubmitCallback!(content); } }), ), @@ -332,7 +329,7 @@ class __SearchInputWidgetState extends State<_SearchInputWidget> { onTap: () { _controller.clear(); if (widget.clearTapCallback != null) { - widget.clearTapCallback(); + widget.clearTapCallback!(); } setState(() {}); }, @@ -358,12 +355,12 @@ class __SearchInputWidgetState extends State<_SearchInputWidget> { ), ValueListenableBuilder( valueListenable: valueNotifier, - builder: (context, value, child) { + builder: (context, bool value, child) { return value ? GestureDetector( onTap: () { if (widget.dismissClickCallback != null) { - widget.dismissClickCallback(_controller, () { + widget.dismissClickCallback!(_controller, () { setState(() {}); }); }