diff --git a/.github/workflows/build_test.yml b/.github/workflows/build_test.yml index b35a486c..fef521c5 100644 --- a/.github/workflows/build_test.yml +++ b/.github/workflows/build_test.yml @@ -20,7 +20,7 @@ jobs: java-version: '8.x' - uses: subosito/flutter-action@v1 with: - flutter-version: '2.2.3' + flutter-version: '2.10.5' - run: dart --version - run: flutter --version - run: flutter pub get @@ -40,7 +40,7 @@ jobs: java-version: '8.x' - uses: subosito/flutter-action@v1 with: - flutter-version: '2.2.3' + flutter-version: '2.10.5' - run: dart --version - run: flutter --version - run: flutter pub get diff --git a/CHANGELOG.md b/CHANGELOG.md index aca34a4f..e39526f8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,41 @@ +## [2.2.0] - 2022-4-29 + +### Changed + +#### base +- Adapt flutter sdk 2.10.5. +- Fix flutter analyze issues. +- Fixed some component theme configurations customization not taking effect [#177](https://github.com/LianjiaTech/bruno/issues/177) . + +#### components + +**New components** BrnSwitchFormItem BrnGeneralFormItem BrnMetaSwitch. + +- BrnTitleFormItem: fix isRequire parameter invalid [#179](https://github.com/LianjiaTech/bruno/issues/179). +- BrnTextBlockInputFormItem : change the minLines and maxLines attributes to be nullable [#181](https://github.com/LianjiaTech/bruno/pull/181) thanks to **xiao luobei**. +- BrnSelectionView : fix "unlimited" option not taking effect . +- BrnBottomTabBar: remove the restriction on type by item.length in the construction method. +- BrnPairInfoTable adds a callback attribute onFolded for expanding and collapsing state changes. +- BrnCheckbox: add attribute crossAxisAlignment. +- BrnRadioButton: add attribute crossAxisAlignment. +- BrnMiddleInputDialog: add attribute themeData support theme. +- BrnTextButtonPanel: optimize button display, fix the space cannot be filled in some cases. +- BrnCommonCardTitle: add attribute titleMaxLines and titleOverflow. +- BrnMultiSelectDialog: uses the default contentStyle of BrnDialogConfig. +- BrnScrollableTextDialog: optimize ScrollBar placement and styling. +- BrnSingleSelectDialog: Add click callback for closeIcon. +- BrnSelectionView: optimizes the data display of the [More] filter page, and supports the display of up to 2 rows. +- BrnTextInputFormItem BrnTextBlockInputFormItem BrnTitleSelectInputFormItem : add attribute autofocus and default value is false. +- BrnAppBar theme customization BrnAppBarConfig supports the attribute showDefaultBottom to control the bottom dividing line of the AppBar +- BrnMultiDataPicker: add default delegate implementationBrnDefaultMultiDataPickerDelegate. +- BrnStepInputFormItem: add attribute canManualInput and controller to support manual input function. +- BrnPairInfoTable: add a callback onExpanded for expanding and collapsing state changes. +- BrnSearchText: add attribute inputFormatterstextInputType. +- BrnAnchorTab: support content dynamic change. +- BrnProgressBarChart: when barChartStyle is BarChartStyle.horizontal support item click callback. + + + ## [2.1.1] - 2022-4-1 ### Changed diff --git a/README.en-US.md b/README.en-US.md index 56120bac..bf28ddc7 100644 --- a/README.en-US.md +++ b/README.en-US.md @@ -27,6 +27,12 @@ An enterprise-class package of Flutter components for mobile applications. ![](https://img.ljcdn.com/beike/zjz/bruno/img/1638883534391.png) +#### New components :tada: :tada: :tada: + +BrnSwitchButton BrnSwitchFormItem BrnGeneralFormItem + + + ## ✨ Features * Enterprise-class UI designed for mobile applications. @@ -49,6 +55,7 @@ If you cannot access the demo, you can directly watch [Overview](https://github. | 1.0.0 | 1.22.4 | | 2.0.0 | 2.2.2 | | 2.1.1 (support nullsafety) | 2.2.2 | +| 2.2.0 | 2.10.5 | ## Preparing for use diff --git a/README.md b/README.md index 11d3ef29..1f1b1696 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,13 @@ ![](https://img.ljcdn.com/beike/zjz/bruno/img/1638883534391.png) +#### 组件上新 :tada: :tada: :tada: + +BrnSwitchButton BrnSwitchFormItem BrnGeneralFormItem + + + + ## ✨ 特性 @@ -45,6 +52,7 @@ | 1.0.0 | 1.22.4 | | 2.0.0 | 2.2.2 | | 2.1.1 (支持空安全) | 2.2.2 | +| 2.2.0 | 2.10.5 | diff --git a/analysis_options.yaml b/analysis_options.yaml new file mode 100644 index 00000000..80f2c75c --- /dev/null +++ b/analysis_options.yaml @@ -0,0 +1,6 @@ +include: package:lints/core.yaml +# include: package:lints/recommended.yaml + +analyzer: + exclude: + - doc/** diff --git a/doc/components/actionsheet/BrnCommonActionSheet/BrnCommonActionSheet.md b/doc/components/actionsheet/BrnCommonActionSheet/BrnCommonActionSheet.md index 22d190f7..912ae432 100644 --- a/doc/components/actionsheet/BrnCommonActionSheet/BrnCommonActionSheet.md +++ b/doc/components/actionsheet/BrnCommonActionSheet/BrnCommonActionSheet.md @@ -53,19 +53,19 @@ BrnCommonActionSheet({ ### 参数说明 -| **参数名** | **参数类型** | **描述** | **是否必填** | **默认值** | -| ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------ | ------------------------- | -| actions | `List` | 用于存储每个选项的相关配置信息的列表(BrnActionItem 含有参数 title---选项标题文案(**必填**),desc----辅助信息文案,actionEleStyle----普通项或警示项,titleStyle---自定义主标题文本样式(覆盖 actionEleStyle)descStyle---自定义辅助信息文本样式(覆盖 actionEleStyle)) | 是 | 空 | -| title | String? | 列表标题的文案 | 否 | 空 | -| titleWidget | Widget? | 列表标题区域自定义 Widget | 否 | 空 | -| cancelTitle | String? | 取消按钮的文案 | 否 | ''取消'' | -| maxTitleLines | Int | 列表标题文案最大行数 | 否 | 2 | -| onItemClickInterceptor | BrnCommonActionSheetItemClickInterceptor? =void( int index, BrnCommonActionSheetItem actionItem)? | **返回值为 bool**,返回值用于判断是否拦截点击事件,如果为**true**将拦截,用户点击将**不会触发 clickCallBack**,当前 actionSheet 也**不会消失**。如果为**false**,则不会造成任何影响,只是提前拦截了一下点击事件。 | 否 | 空 | -| clickCallBack(默认回调后会执行 pop 操作,如过不想 pop,请使用 onItemClickInterceptor) | BrnCommonActionSheetItemClickCallBack?=void ( int index, BrnCommonActionSheetItem actionItem)? | **返回值为 void**,点击后回调方法(方法传参为被点击的按钮的**index**及相关配置信息**BrnActionItem**),使用者**根据参数自行配置响应动作**。 | 是 | 空 | -| spaceColor | Color | “取消”按钮上方间隔颜色 | 否 | **Color(0xfff8f8f8)**浅灰 | -| separatorLineColor | Color? | 分割线颜色 | 否 | **Color(0xfff0f0f0)**浅灰 | -| maxSheetHeight | double | 列表最大高度限制 | 否 | 默认为0 | -| themeData | BrnActionSheetConfig? | ActionSheet 主题配置类,支持配置字段详见 BrnActionSheetConfig | 否 | | +| **参数名** | **参数类型** | **描述** | **是否必填** | **默认值** | +| ------------------------------------------------------------ | ----------------------------------------- | ------------------------------------------------------------ | ------------ | ------------------------- | +| actions | `List` | 用于存储每个选项的相关配置信息的列表(BrnActionItem 含有参数 title---选项标题文案(**必填**),desc----辅助信息文案,actionEleStyle----普通项或警示项,titleStyle---自定义主标题文本样式(覆盖 actionEleStyle)descStyle---自定义辅助信息文本样式(覆盖 actionEleStyle)) | 是 | 空 | +| title | String? | 列表标题的文案 | 否 | 空 | +| titleWidget | Widget? | 列表标题区域自定义 Widget | 否 | 空 | +| cancelTitle | String? | 取消按钮的文案 | 否 | ''取消'' | +| maxTitleLines | Int | 列表标题文案最大行数 | 否 | 2 | +| onItemClickInterceptor | BrnCommonActionSheetItemClickInterceptor? | **返回值为 bool**,返回值用于判断是否拦截点击事件,如果为**true**将拦截,用户点击将**不会触发 clickCallBack**,当前 actionSheet 也**不会消失**。如果为**false**,则不会造成任何影响,只是提前拦截了一下点击事件。 | 否 | 空 | +| clickCallBack(默认回调后会执行 pop 操作,如过不想 pop,请使用 onItemClickInterceptor) | BrnCommonActionSheetItemClickCallBack? | **返回值为 void**,点击后回调方法(方法传参为被点击的按钮的**index**及相关配置信息**BrnActionItem**),使用者**根据参数自行配置响应动作**。 | 是 | 空 | +| spaceColor | Color | “取消”按钮上方间隔颜色 | 否 | **Color(0xfff8f8f8)**浅灰 | +| separatorLineColor | Color? | 分割线颜色 | 否 | **Color(0xfff0f0f0)**浅灰 | +| maxSheetHeight | double | 列表最大高度限制 | 否 | 默认为0 | +| themeData | BrnActionSheetConfig? | ActionSheet 主题配置类,支持配置字段详见 BrnActionSheetConfig | 否 | | ## 四、代码演示 diff --git a/doc/components/actionsheet/BrnShareActionSheet/BrnShareActionSheet.md b/doc/components/actionsheet/BrnShareActionSheet/BrnShareActionSheet.md index f37fef55..bf925199 100644 --- a/doc/components/actionsheet/BrnShareActionSheet/BrnShareActionSheet.md +++ b/doc/components/actionsheet/BrnShareActionSheet/BrnShareActionSheet.md @@ -72,12 +72,12 @@ BrnShareActionSheet({ | firstShareChannels | `List?` | 第一行渠道列表 | 否 | 空 | | secondShareChannels | `List?` | 第二行渠道列表 | 否 | | | mainTitle | String? | 列表标题 | 否 | | -| clickCallBack | BrnShareActionSheetItemClickCallBack=void ( int section, int index, BrnShareItem shareItem)? | 点击分享渠道图标后回调方法 | 否 | 空 | +| clickCallBack | BrnShareActionSheetItemClickCallBack? | 点击分享渠道图标后回调方法 | 否 | 空 | | cancelTitle | String? | 取消按钮的文案 | 否 | ''取消'' | | context | BuildContext | BuidContext | 是 | 空 | | shareTextColor | Color | 分享渠道文案颜色 | 否 | Color(0xff999999)灰色 | | textColor | Color | 选项标题颜色 | 否 | Color(0xff222222)黑色 | -| clickInterceptor | BrnShareActionSheetOnItemClickInterceptor? = void (int section, int index, BrnShareItem shareItem)? | 是否可点击(如果为预设类型,设置为不可点击后会变为相应的置灰图标)默认为true | 否 | | +| clickInterceptor | BrnShareActionSheetOnItemClickInterceptor? | 是否可点击(如果为预设类型,设置为不可点击后会变为相应的置灰图标)默认为true | 否 | | ### 其他数据 diff --git a/doc/components/appraise/BrnAppraise/BrnAppraise.md b/doc/components/appraise/BrnAppraise/BrnAppraise.md index c0ad9aa4..68381da8 100644 --- a/doc/components/appraise/BrnAppraise/BrnAppraise.md +++ b/doc/components/appraise/BrnAppraise/BrnAppraise.md @@ -92,44 +92,44 @@ BrnAppraise( ### 参数说明 -| **参数名** | **参数类型** | **作用** | **是否必填** | **默认值** | -| ---------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------ | -------------------------------------- | -| title | String | 标题 | 否 | '' | -| headerType | BrnAppraiseHeaderType | 标题类型,居中还是两侧 | 否 | BrnAppraiseHeaderType.spaceBetween | -| type | BrnAppraiseType | 评价组件类型,表情包还是五角星 | 否 | BrnAppraiseType.Star | -| iconDescriptions | `List` | 点击表情时对应等级的提示文案。若 `type=BrnAppraiseType.Emoji`,则 list 长度为 5,不足 5 个时请在对应位置补空字符串。若 `type=BrnAppraiseType.Star`,list 长度不能比传入的 BrnAppraiseConfig 中的 count 小。 | 否 | ['不好','还行','满意','很棒','超惊喜'] | -| tags | `List?` | 供选择的标签数据 | 否 | 无 | -| inputHintText | String | 输入框的提示文字 | 否 | '' | -| onConfirm | `void Function(int index, List selectedTags, String input)?` | 点击提交时的回调,其中 index 是选中的表情或者五角星的 index,selectedTags 是选中的标签,input 是输入框的内容 | 否 | 无 | -| config | BrnAppraiseConfig | 配置类,具体见下边其他参数说明 | 否 | BrnAppraiseConfig() | +| **参数名** | **参数类型** | **作用** | **是否必填** | **默认值** | +| ---------------- | ------------------------ | ------------------------------------------------------------ | ------------ | -------------------------------------- | +| title | String | 标题 | 否 | '' | +| headerType | BrnAppraiseHeaderType | 标题类型,居中还是两侧 | 否 | BrnAppraiseHeaderType.spaceBetween | +| type | BrnAppraiseType | 评价组件类型,表情包还是五角星 | 否 | BrnAppraiseType.Star | +| iconDescriptions | `List` | 点击表情时对应等级的提示文案。若 `type=BrnAppraiseType.Emoji`,则 list 长度为 5,不足 5 个时请在对应位置补空字符串。若 `type=BrnAppraiseType.Star`,list 长度不能比传入的 BrnAppraiseConfig 中的 count 小。 | 否 | ['不好','还行','满意','很棒','超惊喜'] | +| tags | `List?` | 供选择的标签数据 | 否 | 无 | +| inputHintText | String | 输入框的提示文字 | 否 | '' | +| onConfirm | BrnAppraiseConfirmClick? | 点击提交时的回调,其中 index 是选中的表情或者五角星的 index,selectedTags 是选中的标签,input 是输入框的内容 | 否 | 无 | +| config | BrnAppraiseConfig | 配置类,具体见下边其他参数说明 | 否 | BrnAppraiseConfig() | ### 其他参数说明 #### BrnAppraiseConfig -| **参数名** | **参数类型** | **作用** | **是否必填** | **默认值** | -| ----------------------- | ------------------------------------------- | ------------------------------------------------------------ | ------------ | ------------------------------------------------------------ | -| showHeader | bool | 是否显示顶部标题和关闭按钮的 header 视图 | 否 | true | -| headerPadding | EdgeInsets? | header 部分的 padding,只有居中样式支持设置 | 否 | `headerType=BrnAppraiseHeader.center`时,为 `EdgeInsets.only(top: 20, bottom: 20)`,其余为 `EdgeInsets.only(left: 20, top: 16, right: 16, bottom: 20)` | -| titleMaxLines | int | 标题的最大行数 | 否 | 1 | -| onCancel | `void Function(BuildContext context)?` | 点击关闭按钮时的回调 | 否 | 无 | -| count | int | `type=BrnAppraiseType.Star`时所需五角星的个数 | 否 | 5 | -| iconDescriptions | `List` | 点击表情时的文案。`type=BrnAppraiseType.Star`时,该列表的数据个数不能比 count 少。`type=BrnAppraiseType.Emoji`时,list 长度应为 5,不足 5 个时请在对应位置补空字符串 | 否 | ['不好', '还行', '满意', '很棒', '超惊喜'] | -| indexes | `List` | 表情包打分组件所需表情的 index | 否 | [0,1,2,3,4] | -| starAppraiseHint | String | 五角星未打分时的提示文案 | 否 | '' | -| multiSelect | bool | 标签是否支持多选 | 否 | true | -| tagCountEachRow | int | 每行显示的标签数 | 否 | 2 | -| showTextInput | bool | 是否显示输入框 | 否 | true | -| maxLength | int | 输入框能输入文字的最大长度 | 否 | 100 | -| maxHintLines | int | 提示文案的最大行数 | 否 | 1 | -| inputDefaultText | String? | 输入框默认文案 | 否 | 无 | -| inputMaxHeight | double | 输入框的最大高度 | 否 | 120 | -| showConfirmButton | bool | 是否显示提交按钮 | 否 | true | -| confirmButtonText | String | 提交按钮自定义文案 | 否 | '提交' | -| isConfirmButtonEnabled | bool | 提交按钮的可用状态 | 否 | 默认 null,在打分之后 enable | -| iconClickCallback | `void Function(int index)?` | 点击打分时的回调 | 否 | 无 | -| inputTextChangeCallback | `void Function(String input)?` | 输入框内容改变的回调 | 否 | 无 | -| tagSelectCallback | `void Function(List selectedTags)?` | 选择标签时的回调 | 否 | 无 | +| **参数名** | **参数类型** | **作用** | **是否必填** | **默认值** | +| ----------------------- | ------------------------------ | ------------------------------------------------------------ | ------------ | ------------------------------------------------------------ | +| showHeader | bool | 是否显示顶部标题和关闭按钮的 header 视图 | 否 | true | +| headerPadding | EdgeInsets? | header 部分的 padding,只有居中样式支持设置 | 否 | `headerType=BrnAppraiseHeader.center`时,为 `EdgeInsets.only(top: 20, bottom: 20)`,其余为 `EdgeInsets.only(left: 20, top: 16, right: 16, bottom: 20)` | +| titleMaxLines | int | 标题的最大行数 | 否 | 1 | +| onCancel | BrnAppraiseCloseClickCallBack? | 点击关闭按钮时的回调 | 否 | 无 | +| count | int | `type=BrnAppraiseType.Star`时所需五角星的个数 | 否 | 5 | +| iconDescriptions | `List` | 点击表情时的文案。`type=BrnAppraiseType.Star`时,该列表的数据个数不能比 count 少。`type=BrnAppraiseType.Emoji`时,list 长度应为 5,不足 5 个时请在对应位置补空字符串 | 否 | ['不好', '还行', '满意', '很棒', '超惊喜'] | +| indexes | `List` | 表情包打分组件所需表情的 index | 否 | [0,1,2,3,4] | +| starAppraiseHint | String | 五角星未打分时的提示文案 | 否 | '' | +| multiSelect | bool | 标签是否支持多选 | 否 | true | +| tagCountEachRow | int | 每行显示的标签数 | 否 | 2 | +| showTextInput | bool | 是否显示输入框 | 否 | true | +| maxLength | int | 输入框能输入文字的最大长度 | 否 | 100 | +| maxHintLines | int | 提示文案的最大行数 | 否 | 1 | +| inputDefaultText | String? | 输入框默认文案 | 否 | 无 | +| inputMaxHeight | double | 输入框的最大高度 | 否 | 120 | +| showConfirmButton | bool | 是否显示提交按钮 | 否 | true | +| confirmButtonText | String | 提交按钮自定义文案 | 否 | '提交' | +| isConfirmButtonEnabled | bool | 提交按钮的可用状态 | 否 | 默认 null,在打分之后 enable | +| iconClickCallback | BrnAppraiseIconClick? | 点击打分时的回调 | 否 | 无 | +| inputTextChangeCallback | BrnInputTextChangeCallback? | 输入框内容改变的回调 | 否 | 无 | +| tagSelectCallback | BrnAppraiseTagClick? | 选择标签时的回调 | 否 | 无 | ```dart const BrnAppraiseConfig({ diff --git a/doc/components/bottomTabBar/BrnBottomTabBar/BrnBottomTabBar.md b/doc/components/bottomTabBar/BrnBottomTabBar/BrnBottomTabBar.md index 10c268e4..6171d737 100644 --- a/doc/components/bottomTabBar/BrnBottomTabBar/BrnBottomTabBar.md +++ b/doc/components/bottomTabBar/BrnBottomTabBar/BrnBottomTabBar.md @@ -29,7 +29,7 @@ BrnBottomTabBar({ required this.items, this.onTap, this.currentIndex = 0, - BrnBottomTabBarDisplayType type = BrnBottomTabBarDisplayType.fixed, + this.type = BrnBottomTabBarDisplayType.fixed, this.fixedColor, this.iconSize = 24.0, this.isAnimation = false, @@ -41,9 +41,6 @@ BrnBottomTabBar({ 'Every item must have a non-null title', ), assert(0 <= currentIndex && currentIndex < items.length), - type = items.length <= 3 - ? BrnBottomTabBarDisplayType.fixed - : BrnBottomTabBarDisplayType.shifting, super(key: key); ``` diff --git a/doc/components/charts/BrnProgressBarChart/BrnProgressBarChart.md b/doc/components/charts/BrnProgressBarChart/BrnProgressBarChart.md index ac64e1c4..ff8c9880 100644 --- a/doc/components/charts/BrnProgressBarChart/BrnProgressBarChart.md +++ b/doc/components/charts/BrnProgressBarChart/BrnProgressBarChart.md @@ -73,8 +73,8 @@ BrnProgressBarChart( | barMaxValue | double | 柱状图最大值 | 否 | 0 | | selectedHintTextColor | Color | 选中柱状图提示文案文本颜色 | 否 | Colors.white | | selectedHintTextBackgroundColor | Color | 选中柱状图提示文案文本背景颜色 | 否 | Colors.black | -| barChartSelectCallback | void Function(BarItem barItem) | 选中柱状图时候的回调 | 否 | | -| onBarItemClickInterceptor | bool OnBarItemClickInterceptor(int barBundleIndex, BarBundle barBundle, int barGroupIndex, BarItem barItem) | 柱状图是否可点击回调 | 否 | | +| barChartSelectCallback | BrnProgressBarChartSelectCallback | 选中柱状图时候的回调 | 否 | | +| onBarItemClickInterceptor | OnBarItemClickInterceptor | 柱状图是否可点击回调 | 否 | | ## 四、代码演示 diff --git a/doc/components/checkbox/BrnCheckbox/BrnCheckbox.md b/doc/components/checkbox/BrnCheckbox/BrnCheckbox.md index e9699d85..5162b770 100644 --- a/doc/components/checkbox/BrnCheckbox/BrnCheckbox.md +++ b/doc/components/checkbox/BrnCheckbox/BrnCheckbox.md @@ -39,6 +39,7 @@ const BrnCheckbox({ this.child, this.childOnRight = true, this.mainAxisAlignment = MainAxisAlignment.start, + this.crossAxisAlignment = CrossAxisAlignment.center, this.mainAxisSize = MainAxisSize.min, }); ``` @@ -54,6 +55,7 @@ const BrnCheckbox({ | iconPadding | EdgeInsets | 选择图标的padding | 否 | EdgeInsets.all(5) | | childOnRight | bool | widget在是否在选择 icon 的右边,false 就在左边 | 否 | true | | mainAxisAlignment | MainAxisAlignment | child 视图和 icon 在row布局里面的alignment | 否 | MainAxisAlignment.start | +| crossAxisAlignment | CrossAxisAlignment | child 视图和 icon 在row布局里面的CrossAlignment | 否 | CrossAxisAlignment.center | | mainAxisSize | MainAxisSize | child 视图和 icon 在row布局里面的mainAxisSize | 否 | MainAxisSize.min | ## 四、代码演示 diff --git a/doc/components/dashedLine/BrnDashedLine/BrnDashedLine.md b/doc/components/dashedLine/BrnDashedLine/BrnDashedLine.md index 6850c05c..307ef692 100644 --- a/doc/components/dashedLine/BrnDashedLine/BrnDashedLine.md +++ b/doc/components/dashedLine/BrnDashedLine/BrnDashedLine.md @@ -28,7 +28,7 @@ group: ```dart -BrnMetaDashedLine({ +BrnDashedLine({ Key key, @required this.contentWidget, this.axis, @@ -61,7 +61,7 @@ BrnMetaDashedLine({ ```dart // 内部有内容 -BrnMetaDashedLine( +BrnDashedLine( dashedLength: 20, dashedThickness: 5, axis: Axis.vertical, @@ -81,7 +81,7 @@ BrnMetaDashedLine( ```dart // 内部没有内容 -BrnMetaDashedLine( +BrnDashedLine( dashedLength: 10, dashedThickness: 3, axis: Axis.horizontal, @@ -106,7 +106,7 @@ Container( width: 300, padding: EdgeInsets.all(5), color: Colors.red, - child: BrnMetaDashedLine( + child: BrnDashedLine( axis: Axis.horizontal, dashedOffset: 10, ), diff --git a/doc/components/dialog/BrnMiddleInputDialog/BrnMiddleInputDialog.md b/doc/components/dialog/BrnMiddleInputDialog/BrnMiddleInputDialog.md index 9dd40a66..3d8cabca 100644 --- a/doc/components/dialog/BrnMiddleInputDialog/BrnMiddleInputDialog.md +++ b/doc/components/dialog/BrnMiddleInputDialog/BrnMiddleInputDialog.md @@ -41,7 +41,8 @@ const BrnMiddleInputDialog( this.onCancel, this.dismissOnActionsTap = true, this.barrierDismissible = true, - this.autoFocus = false}); + this.autoFocus = false, + this.themeData,}); ``` ### 参数说明 @@ -64,7 +65,7 @@ const BrnMiddleInputDialog( | dismissOnActionsTap | bool | 点击取消/确认按钮之后,是否自动关闭弹窗 | 否 | true | | barrierDismissible | bool | 点击蒙层背景,弹窗是否可关闭。 | 否 | true | | autoFocus | bool | 是否自动获取焦点,弹出键盘 | 否 | false | - +| themeData | BrnDialogConfig | 主题定制配置 | 否 | defaultDialogConfig | ## 四、效果及代码展示 diff --git a/doc/components/dialog/BrnShareDialog/BrnShareDialog.md b/doc/components/dialog/BrnShareDialog/BrnShareDialog.md index 59109a4d..92d831f2 100644 --- a/doc/components/dialog/BrnShareDialog/BrnShareDialog.md +++ b/doc/components/dialog/BrnShareDialog/BrnShareDialog.md @@ -69,7 +69,7 @@ BrnShareDialog({ | descText | String? | 弹框辅助信息文案(为空则**不显示**辅助信息) | 否 | 无 | | separatorText | String? | 文案与分享渠道图标间的分割线内嵌文案 | 否 | 你可以通过以下方式分享给客户 | | shareChannels | `List` | 用于表示所展示的分享渠道图标的索引(列表内容可直接填写渠道对应的**int**值,或使用**BrnShareItemConstants**的静态变量,例如**BrnShareItemConstants.SHARE\_WEIXIN**)。自定义为100或**BrnShareItemConstants.SHARE\_CUSTOM**。 | 是 | 空 | -| clickCallBack | BrnShareDialogItemClickCallBack(int shareChannel, int customIndex) | 点击分享渠道图标后回调方法(方法传参为被点击的分享渠道图标在**BrnShareItemConstants**中的索引值shareChannel, 及改列表在使用者自定义的*shareChannels*中的索引值customIndex),使用者**根据参数自行配置响应动作**。 | 否 | 空 | +| clickCallBack | BrnShareDialogItemClickCallBack? | 点击分享渠道图标后回调方法(方法传参为被点击的分享渠道图标在**BrnShareItemConstants**中的索引值shareChannel, 及改列表在使用者自定义的*shareChannels*中的索引值customIndex),使用者**根据参数自行配置响应动作**。 | 否 | 空 | | getCustomChannelTitle | BrnShareDialogGetCustomShareItemTitle? | 获取自定义分享渠道对应的显示**文案**(方法传参为该自定义分享渠道在*shareChannels*中的索引值index)。回调返回值为**String**,如果返回值为空,则**不显示**该自定义分享渠道。 | 否 | 空 | | getCustomChannelWidget | BrnShareDialogGetCustomShareItemIcon? | 获取自定义分享渠道对应的显示**图标**(方法传参为该自定义分享渠道在*shareChannels*中的索引值index)。回调返回值为**Widget**,如果返回值为空,则**不显示**该自定义分享渠道。 | 否 | 空 | | context | BuildContext | BuildContext | 是 | 空 | diff --git a/doc/components/dialog/BrnSingleSelectDialog/BrnSingleSelectDialog.md b/doc/components/dialog/BrnSingleSelectDialog/BrnSingleSelectDialog.md index f5212325..5b6bfcca 100644 --- a/doc/components/dialog/BrnSingleSelectDialog/BrnSingleSelectDialog.md +++ b/doc/components/dialog/BrnSingleSelectDialog/BrnSingleSelectDialog.md @@ -36,27 +36,29 @@ const BrnSingleSelectDialog( this.onItemClick, this.checkedItem, this.customWidget, + this.onCloseClick, this.canDismissOnConfirmClick = true, this.isCustomFollowScroll = true}); ``` ### 参数说明 -| **参数名** | **参数类型** | **描述** | **是否必填** | **默认值** | -| ------------------------ | ----------------------------------- | --------------------------------------------------------- | ------------ | ---------- | -| isClose | bool | 用于控制弹窗是否相应电机外部关闭,true 关闭,false 不关闭 | 否 | true | -| title | String | 弹窗标题名称 | 否 | "" | -| messageText | String? | 描述文案,优先级较 messageWidget 低,优先使用 messageWidget | 否 | | -| messageWidget | Widget? | 描述 Widget | 否 | | -| conditions | List | 备选项数组 | 否 | | -| checkedItem | String | 选中的选项名称 | 否 | | -| submitText | String | 确定/提交 按钮文案 | 否 | | -| submitBgColor | Color | 提交按钮背景颜色 | 否 | | -| customWidget | Widget | 在单选列表底部自定义 Widget | 否 | null | -| isCustomFollowScroll | bool | 内容是否可滑动 | 否 | true | -| canDismissOnConfirmClick | bool | 是否在点击时让 Diallog 消失 | 否 | true | -| onSubmitClick | BrnSingleSelectOnSubmitCallback? | 提交按钮点击的回调 | 否 | | -| onItemClick | BrnSingleSelectOnItemClickCallback? | item 的点击回调 | 否 | | +| **参数名** | **参数类型** | **描述** | **是否必填** | **默认值** | +| ------------------------ | ----------------------------------- | ----------------------------------------------------------- | ------------ | ---------- | +| isClose | bool | 用于控制弹窗是否相应电机外部关闭,true 关闭,false 不关闭 | 否 | true | +| title | String | 弹窗标题名称 | 否 | "" | +| messageText | String? | 描述文案,优先级较 messageWidget 低,优先使用 messageWidget | 否 | | +| messageWidget | Widget? | 描述 Widget | 否 | | +| conditions | List | 备选项数组 | 否 | | +| checkedItem | String | 选中的选项名称 | 否 | | +| submitText | String | 确定/提交 按钮文案 | 否 | | +| submitBgColor | Color | 提交按钮背景颜色 | 否 | | +| customWidget | Widget | 在单选列表底部自定义 Widget | 否 | null | +| onCloseClick | VoidCallback | 点击关闭 icon 的回调 | 否 | null | +| isCustomFollowScroll | bool | 内容是否可滑动 | 否 | true | +| canDismissOnConfirmClick | bool | 是否在点击时让 Diallog 消失 | 否 | true | +| onSubmitClick | BrnSingleSelectOnSubmitCallback? | 提交按钮点击的回调 | 否 | | +| onItemClick | BrnSingleSelectOnItemClickCallback? | item 的点击回调 | 否 | | ## 三、代码演示 diff --git a/doc/components/form/BrnGeneralFormItem/BrnGeneralFormItem.md b/doc/components/form/BrnGeneralFormItem/BrnGeneralFormItem.md new file mode 100644 index 00000000..2b94edcb --- /dev/null +++ b/doc/components/form/BrnGeneralFormItem/BrnGeneralFormItem.md @@ -0,0 +1,148 @@ +--- +title: BrnGeneralFormItem +group: + title: Form + order: 12 +--- + +# BrnGeneralFormItem + +## 一、效果总览 + + + +## 二、描述 + +### 适用场景 + +1. 基础表单项框架适用于自定义基础表单项 +2. 可自定义标题、副标题、右侧操作区域 + +包括"标题"、"副标题"、"错误信息提示"、"必填项提示"、"添加/删除按钮"、"消息提示"、"多选项"等元素。 + +### 交互规则 + +1. 设置是否为"必填项"("\*") + +2. 设置“添加/删除”图标("+"、"-"):用于接收回调函数处理新增/删除录入项操作 + +3. 设置“提示”图标&文案("?"):用于接收回调函数为用户展示提示信息 + +4. 设置此录入项是否可编辑(禁用) + +5. 设置展示错误信息(error) + +### 使用规范 + +一般用于扩展基础表单项 + +## 三、构造函数及参数说明 + +### 构造函数 + +```dart +BrnGeneralFormItem({ + Key? key, + this.label, + this.title: "", + this.titleWidget, + this.subTitle, + this.subTitleWidget, + this.tipLabel, + this.prefixIconType = BrnPrefixIconType.normal, + this.error: "", + this.isEdit: true, + this.isRequire: false, + this.operateWidget, + this.onAddTap, + this.onRemoveTap, + this.onTip, + this.themeData, + }): super(key: key){ + this.themeData ??= BrnFormItemConfig(); + this.themeData = BrnThemeConfigurator.instance + .getConfig(configId: this.themeData!.configId) + .formItemConfig + .merge(this.themeData); + } +``` + +### 参数说明: + +| **参数名** | 参数类型 | **描述** | **是否必填** | **默认值** | **备注** | +| --- | --- | --- | --- | --- | --- | +| label | String? | 录入项的唯一标识,主要用于录入类型页面框架中 | 否 | 无 | | +| title | String | 录入项标题 | 否 | '' | | +| titleWidget | Widget? | 录入项标题Widget | 否 | 无 | | +| subTitle | String? | 录入项子标题 | 否 | 无 | | +| subTitleWidget | Widget? | 录入项子标题Widget | 否 | 无 | | +| tipLabel | String? | 录入项提示(问号图标&文案) 用户点击时触发 onTip 回调。 | 否 | 备注中类型 3 | 1. 设置"空字符串"时展示问号图标 2. 设置"非空字符串"时展示问号图标&文案 3. 若不赋值或赋值为 null 时,不显示提示项 | +| prefixIconType | String | 录入项前缀图标样式 "添加项" "删除项" 详见 BrnPrefixIconType 类 | 否 | BrnPrefixIconType.normal | 1. 不展示图标:BrnPrefixIconType.normal 2. 展示加号图标:BrnPrefixIconType.add 3. 展示减号图标:BrnPrefixIconType.remove | +| error | String | 录入项错误提示 | 否 | '' | | +| isRequire | bool | 录入项是否为必填项(展示\*图标) 默认为 false 不必填 | 否 | false | | +| isEdit | bool | 录入项 是否可编辑 | 否 | true | true:可编辑 false:禁用 | +| onAddTap | VoidCallback? | 点击"+"图标回调 | 否 | 无 | 见**prefixIconType**字段 | +| onRemoveTap | VoidCallback? | 点击"-"图标回调 | 否 | 无 | 见**prefixIconType**字段 | +| onTip | VoidCallback? | 点击"?"图标回调 | 否 | 无 | 见**tipLabel**字段 | +| themeData | BrnFormItemConfig? | form 配置 | 否 | 无 | | + +### 其他数据说明: + +#### BrnPrefixIconType: + +```dart +class BrnPrefixIconType { + static const String normal = "type_normal"; + static const String add = "type_add"; + static const String remove = "type_remove"; +} +``` + +## 四、代码演示 + +### 效果 1:基本样式 + + + +```dart +BrnGeneralFormItem( + title: "自然到访保护期", + subTitle: "这里是副标题", + onTip: () { + BrnToast.show("点击触发onTip回调", context); + }, + onAddTap: () { + BrnToast.show("点击触发onAddTap回调", context); + }, + onRemoveTap: () { + BrnToast.show("点击触发onRemoveTap回调", context); + }, +) +``` + +### 效果 2:全功能样式 + + + +```dart +BrnGeneralFormItem( + prefixIconType: BrnPrefixIconType.add, + isRequire: true, + isEdit: true, + error: "必填项不能为空", + titleWidget: Text("自然到访保护期"), + subTitleWidget: Text("这里是副标题"), + tipLabel: "标签", + operateWidget: Text("右侧操作区"), + onTip: () { + BrnToast.show("点击触发onTip回调", context); + }, + onAddTap: () { + BrnToast.show("点击触发onAddTap回调", context); + }, + onRemoveTap: () { + BrnToast.show("点击触发onRemoveTap回调", context); + }, +) +``` + diff --git a/doc/components/form/BrnGeneralFormItem/img/BrnGeneralFormItem1.png b/doc/components/form/BrnGeneralFormItem/img/BrnGeneralFormItem1.png new file mode 100644 index 00000000..4bb09eac Binary files /dev/null and b/doc/components/form/BrnGeneralFormItem/img/BrnGeneralFormItem1.png differ diff --git a/doc/components/form/BrnGeneralFormItem/img/BrnGeneralFormItem2.png b/doc/components/form/BrnGeneralFormItem/img/BrnGeneralFormItem2.png new file mode 100644 index 00000000..f029b16a Binary files /dev/null and b/doc/components/form/BrnGeneralFormItem/img/BrnGeneralFormItem2.png differ diff --git a/doc/components/form/BrnStarsFormItem/BrnStarsFormItem.md b/doc/components/form/BrnStarsFormItem/BrnStarsFormItem.md index dd02d640..84ece609 100644 --- a/doc/components/form/BrnStarsFormItem/BrnStarsFormItem.md +++ b/doc/components/form/BrnStarsFormItem/BrnStarsFormItem.md @@ -87,10 +87,10 @@ BrnStarsFormItem( #### BrnPrefixIconType: ```dart -class BrnPrefixIconType { - static const String TYPE_NORMAL = "type_normal"; - static const String TYPE_ADD = "type_add"; - static const String TYPE_REMOVE = "type_remove"; +class BrnPrefixIconType { + static const String normal = "type_normal"; + static const String add = "type_add"; + static const String remove = "type_remove"; } ``` diff --git a/doc/components/form/BrnStepInputFormItem/BrnStepInputFormItem.md b/doc/components/form/BrnStepInputFormItem/BrnStepInputFormItem.md index 8391b38b..14d02337 100644 --- a/doc/components/form/BrnStepInputFormItem/BrnStepInputFormItem.md +++ b/doc/components/form/BrnStepInputFormItem/BrnStepInputFormItem.md @@ -53,6 +53,8 @@ BrnStepInputFormItem({ this.maxLimit = 10, this.minLimit = 0, this.onChanged, + this.canManualInput = false, + this.controller, this.themeData, }) : assert(value == null || value >= minLimit && value <= maxLimit), super(key: key) { @@ -84,6 +86,8 @@ BrnStepInputFormItem({ | maxLimit | int | 单步上限值 | 否 | 10 | | | minLimit | int | 单步下限值 | 否 | 0 | | | onChanged | OnBrnFormValueChanged? | 递增值变化回调 | 否 | 无 | | +| canManualInput | bool | 是否可手动输入 | 否 | false | | +| controller | TextEditingController? | 输入框控制器 | 否 | 无 | | | themeData | BrnFormItemConfig? | form配置 | 否 | 无 | | ### 其他数据说明: @@ -91,10 +95,10 @@ BrnStepInputFormItem({ #### BrnPrefixIconType ```dart -class BrnPrefixIconType { - static const String TYPE_NORMAL = "type_normal"; - static const String TYPE_ADD = "type_add"; - static const String TYPE_REMOVE = "type_remove"; +class BrnPrefixIconType { + static const String normal = "type_normal"; + static const String add = "type_add"; + static const String remove = "type_remove"; } ``` ## 四、代码演示 diff --git a/doc/components/form/BrnSwitchFormItem/BrnSwitchFormItem.md b/doc/components/form/BrnSwitchFormItem/BrnSwitchFormItem.md new file mode 100644 index 00000000..a51a2ed4 --- /dev/null +++ b/doc/components/form/BrnSwitchFormItem/BrnSwitchFormItem.md @@ -0,0 +1,142 @@ +--- +title: BrnSwitchFormItem +group: + title: Form + order: 12 +--- + +# BrnSwitchFormItem + +## 一、效果总览 + + + + + +## 二、描述 + +### 适用场景 + +1. 带开关表单项组件 +1. 包括"标题"、"副标题"、"错误信息提示"、"必填项提示"、"添加/删除按钮"、"消息提示"、"多选项"等元素。 + +### 交互规则 + +1. 设置是否为"必填项"("\*") + +2. 设置“添加/删除”图标("+"、"-"):用于接收回调函数处理新增/删除录入项操作 + +3. 设置“提示”图标&文案("?"):用于接收回调函数为用户展示提示信息 + +4. 设置此录入项是否可编辑(禁用) + +5. 设置展示错误信息(error) + +### 使用规范 + +一般用于控制表单内容开关。 + +## 三、构造函数及参数说明 + +### 构造函数 + +```dart +BrnSwitchFormItem({ + Key? key, + this.label, + this.title = "", + this.subTitle, + this.tipLabel, + this.prefixIconType = BrnPrefixIconType.normal, + this.error= "", + this.isEdit = true, + this.isRequire = true, + this.onAddTap, + this.onRemoveTap, + this.onTip, + required this.value, + this.onChanged, + this.themeData, + }) : super() { + this.themeData ??= BrnFormItemConfig(); + this.themeData = BrnThemeConfigurator.instance + .getConfig(configId: this.themeData!.configId) + .formItemConfig + .merge(this.themeData); + } +``` + +### 参数说明: + +| **参数名** | 参数类型 | **描述** | **是否必填** | **默认值** | **备注** | +| --- | --- | --- | --- | --- | --- | +| label | String? | 录入项的唯一标识,主要用于录入类型页面框架中 | 否 | 无 | | +| title | String | 录入项标题 | 否 | '' | | +| subTitle | String? | 录入项子标题 | 否 | 无 | | +| tipLabel | String? | 录入项提示(问号图标&文案) 用户点击时触发 onTip 回调。 | 否 | 备注中类型 3 | 1. 设置"空字符串"时展示问号图标 2. 设置"非空字符串"时展示问号图标&文案 3. 若不赋值或赋值为 null 时,不显示提示项 | +| prefixIconType | String | 录入项前缀图标样式 "添加项" "删除项" 详见 BrnPrefixIconType 类 | 否 | BrnPrefixIconType.normal | 1. 不展示图标:BrnPrefixIconType.normal 2. 展示加号图标:BrnPrefixIconType.add 3. 展示减号图标:BrnPrefixIconType.remove | +| error | String | 录入项错误提示 | 否 | '' | | +| isRequire | bool | 录入项是否为必填项(展示\*图标) 默认为 false 不必填 | 否 | false | | +| isEdit | bool | 录入项 是否可编辑 | 否 | true | true:可编辑 false:禁用 | +| onAddTap | VoidCallback? | 点击"+"图标回调 | 否 | 无 | 见**prefixIconType**字段 | +| onRemoveTap | VoidCallback? | 点击"-"图标回调 | 否 | 无 | 见**prefixIconType**字段 | +| value | bool | 初始值 | 是 | 无 | | +| onTip | VoidCallback? | 点击"?"图标回调 | 否 | 无 | 见**tipLabel**字段 | +| themeData | BrnFormItemConfig? | form 配置 | 否 | 无 | | + +### 其他数据说明: + +#### BrnPrefixIconType: + +```dart +class BrnPrefixIconType { + static const String normal = "type_normal"; + static const String add = "type_add"; + static const String remove = "type_remove"; +} +``` + +## 四、代码演示 + +### 效果 1:基本样式 + + + +```dart +BrnSwitchFormItem( + title: "自然到访保护期", + value: _isFirstSwitchOn, + onChanged: (oldValue, newValue) { + setState(() { + _isFirstSwitchOn = newValue; + }); + BrnToast.show( + "点击触发回调${oldValue}_${newValue}_onChanged", context); + }, +) +``` + +### 效果 2:全功能样式 + + + +```dart +BrnSwitchFormItem( + prefixIconType: BrnPrefixIconType.add, + isRequire: true, + isEdit: true, + error: "必填项不能为空", + title: "自然到访保护期", + subTitle: "这里是副标题", + tipLabel: "标签", + value: _isSecondSwitchOn, + onChanged: (oldValue, newValue) { + setState(() { + _isSecondSwitchOn = newValue; + }); + BrnToast.show( + "点击触发回调${oldValue}_${newValue}_onChanged", context); + }, +) +``` + diff --git a/doc/components/form/BrnSwitchFormItem/img/BrnSwitchItem1.png b/doc/components/form/BrnSwitchFormItem/img/BrnSwitchItem1.png new file mode 100644 index 00000000..32f1ca97 Binary files /dev/null and b/doc/components/form/BrnSwitchFormItem/img/BrnSwitchItem1.png differ diff --git a/doc/components/form/BrnSwitchFormItem/img/BrnSwitchItem2.png b/doc/components/form/BrnSwitchFormItem/img/BrnSwitchItem2.png new file mode 100644 index 00000000..853b6855 Binary files /dev/null and b/doc/components/form/BrnSwitchFormItem/img/BrnSwitchItem2.png differ diff --git a/doc/components/form/BrnTextBlockInputFormItem/BrnTextBlockInputFormItem.md b/doc/components/form/BrnTextBlockInputFormItem/BrnTextBlockInputFormItem.md index 82dc179d..9433bbb8 100644 --- a/doc/components/form/BrnTextBlockInputFormItem/BrnTextBlockInputFormItem.md +++ b/doc/components/form/BrnTextBlockInputFormItem/BrnTextBlockInputFormItem.md @@ -58,6 +58,7 @@ BrnTextBlockInputFormItem( this.onChanged, this.hint = "请输入", this.maxCharCount, + this.autofocus: false, this.inputType, this.inputFormatters, this.controller, @@ -91,12 +92,13 @@ BrnTextBlockInputFormItem( | onTip | VoidCallback? | 点击"?"图标回调 | 否 | 无 | 见**tipLabel**字段 | | hint | String | 录入项 hint 提示 | 否 | "请输入" | | | maxCharCount | int? | 最大输入字符数 | 否 | 无 | | +| autofocus | bool | 是否自动获取焦点 | 否 | false | | | inputType | String? | 输入内容类型,指定键盘类型,参见 `BrnInputType` | 否 | 无 | 详见**BrnInputType**类,注意:无法通过指定键盘类型确保输入。比如不能通过指定数字键盘确保用户只输入数字。如果有要求用户只输入特定字符的需求请使用**inputFormatters**参数 | | inputFormatters | `List?` | 指定对输入数据的格式化要求 | 否 | 无 | | | onChanged | `ValueChanged?` | 输入文案回调 | 否 | 无 | | | controller | TextEditingController? | 文本输入controller | 否 | 无 | | -| minLines | int | 最小行数 | 否 | 4 | | -| maxLines | int | 最大行数 | 否 | 20 | | +| minLines | int? | 最小行数 | 否 | 4 | | +| maxLines | int? | 最大行数 | 否 | 20 | | | themeData | BrnFormItemConfig? | 表单主题配置 | 否 | 无 | | ### 其他数据说明 diff --git a/doc/components/form/BrnTextInputFormItem/BrnTextInputFormItem.md b/doc/components/form/BrnTextInputFormItem/BrnTextInputFormItem.md index 348eba16..5ba14897 100644 --- a/doc/components/form/BrnTextInputFormItem/BrnTextInputFormItem.md +++ b/doc/components/form/BrnTextInputFormItem/BrnTextInputFormItem.md @@ -59,6 +59,7 @@ BrnTextInputFormItem({ this.hint = "请输入", this.unit, this.maxCharCount, + this.autofocus: false, this.inputType, this.inputFormatters, this.onChanged, @@ -93,6 +94,7 @@ BrnTextInputFormItem({ | hint | String | 录入项 hint 提示 | 否 | "请输入" | | | unit | String? | 单位 | 否 | 无 | | | maxCharCount | int? | 最大输入字符数 | 否 | 无 | | +| autofocus | bool | 是否自动获取焦点 | 否 | false | | | inputType | String? | 输入内容类型,指定键盘类型,参见 `BrnInputType` | 否 | 无 | 详见**BrnInputType**类,注意:无法通过指定键盘类型确保输入。比如不能通过指定数字键盘确保用户只输入数字。如果有要求用户只输入特定字符的需求请使用**inputFormatters**参数 | | inputFormatters | `List?` | 指定对输入数据的格式化要求 | 否 | 无 | | | onChanged | `ValueChanged?` | 输入文案回调 | 否 | 无 | | @@ -105,10 +107,10 @@ BrnTextInputFormItem({ ```dart -class BrnPrefixIconType { - static const String TYPE_NORMAL = "type_normal"; - static const String TYPE_ADD = "type_add"; - static const String TYPE_REMOVE = "type_remove"; +class BrnPrefixIconType { + static const String normal = "type_normal"; + static const String add = "type_add"; + static const String remove = "type_remove"; } ``` #### BrnInputType diff --git a/doc/components/form/BrnTitleSelectInputFormItem/BrnTitleSelectInputFormItem.md b/doc/components/form/BrnTitleSelectInputFormItem/BrnTitleSelectInputFormItem.md index b798f568..cfd9ceff 100644 --- a/doc/components/form/BrnTitleSelectInputFormItem/BrnTitleSelectInputFormItem.md +++ b/doc/components/form/BrnTitleSelectInputFormItem/BrnTitleSelectInputFormItem.md @@ -58,6 +58,7 @@ BrnTitleSelectInputFormItem( this.inputType = BrnInputType.TEXT, this.selectedIndex = -1, this.inputFormatters, + this.autofocus: false, this.onChanged, this.onTitleSelected, this.controller, @@ -92,6 +93,7 @@ this.themeData = BrnThemeConfigurator.instance | maxCount | int? | 最大输入字符数 | 否 | 无 | | | inputType | String | 指定键盘类型 | 否 | BrnInputType.TEXT | 详见**BrnInputType**类,注意:无法通过指定键盘类型确保输入。比如不能通过指定数字键盘确保用户只输入数字。如果有要求用户只输入特定字符的需求请使用**inputFormatters**参数 | | inputFormatters | `List?` | 指定对输入数据的格式化要求 | 否 | 无 | | +| autofocus | bool | 是否自动获取焦点 | 否 | false | | | onChanged | `ValueChanged?` | 输入文本变化回调 | 否 | 无 | | | controller | TextEditingController? | 文本输入controller | 否 | 无 | | | selectedIndex | int | 当前Title选中索引 | 否 | -1 | | diff --git a/doc/components/normalButton/BrnBigMainButton/BrnBigMainButton.md b/doc/components/normalButton/BrnBigMainButton/BrnBigMainButton.md index c5e7b70f..2c4462c5 100644 --- a/doc/components/normalButton/BrnBigMainButton/BrnBigMainButton.md +++ b/doc/components/normalButton/BrnBigMainButton/BrnBigMainButton.md @@ -70,7 +70,7 @@ BrnBigMainButton( ```dart //置灰效果 无法点击 -BrnMetaBigMainButtonWidget( +BrnBigMainButton( title: '提交', isEnable: false, onTap: () { diff --git a/doc/components/picker/BrnMultiSelectTagsPicker/BrnMultiSelectTagsPicker.md b/doc/components/picker/BrnMultiSelectTagsPicker/BrnMultiSelectTagsPicker.md index fc7b58ef..096109b7 100644 --- a/doc/components/picker/BrnMultiSelectTagsPicker/BrnMultiSelectTagsPicker.md +++ b/doc/components/picker/BrnMultiSelectTagsPicker/BrnMultiSelectTagsPicker.md @@ -90,10 +90,7 @@ class BrnTagsPickerConfig { this.tagBackgroudColor, this.selectedTagBackgroudColor, this.chipPadding, - this.tagItemSource = const []}) { - this.tagTitleColor = - BrnThemeConfigurator.instance.getConfig().commonConfig.colorTextBase; - } + this.tagItemSource = const []}); ///tag 文字大小 double tagTitleFontSize; diff --git a/doc/components/radio/BrnRadioButton/BrnRadioButton.md b/doc/components/radio/BrnRadioButton/BrnRadioButton.md index 545cb373..624c4243 100644 --- a/doc/components/radio/BrnRadioButton/BrnRadioButton.md +++ b/doc/components/radio/BrnRadioButton/BrnRadioButton.md @@ -39,6 +39,7 @@ const BrnRadioButton( this.child, this.childOnRight = true, this.mainAxisAlignment = MainAxisAlignment.start, + this.crossAxisAlignment = CrossAxisAlignment.center, this.mainAxisSize = MainAxisSize.min, this.behavior = HitTestBehavior.translucent}); ``` @@ -54,6 +55,7 @@ const BrnRadioButton( | iconPadding | EdgeInsets? | 选择图标的padding | 否 | EdgeInsets.all(5) | | childOnRight | bool | widget在是否在选择 icon 的右边,false 就在左边 | 否 | true | | mainAxisAlignment | MainAxisAlignment | child 视图和 icon 在row布局里面的alignment | 否 | MainAxisAlignment.start | +| crossAxisAlignment | CrossAxisAlignment | child 视图和 icon 在row布局里面的CrossAlignment | 否 | CrossAxisAlignment.center | | mainAxisSize | MainAxisSize | child 视图和 icon 在row布局里面的mainAxisSize | 否 | MainAxisSize.min | | behavior | HitTestBehavior | 默认值HitTestBehavior.translucent,控制widget.onRadioItemClick触发的点击范围 | 否 | HitTestBehavior.translucent | diff --git a/doc/components/search/BrnSearchText/BrnSearchText.md b/doc/components/search/BrnSearchText/BrnSearchText.md index ad21dc85..2f703706 100644 --- a/doc/components/search/BrnSearchText/BrnSearchText.md +++ b/doc/components/search/BrnSearchText/BrnSearchText.md @@ -62,6 +62,8 @@ const BrnSearchText({ this.focusNode, this.autoFocus = false, this.textInputAction, + this.inputFormatters, + this.textInputType, }) : super(key: key); ``` @@ -93,6 +95,8 @@ const BrnSearchText({ | focusNode | FocusNode? | 管理焦点 | 否 | 无 | | autofocus | bool | 是否自动获取焦点 | 否 | false | | textInputAction | TextInputAction? | 用于控制键盘动作 | 否 | 无 | +| inputFormatters | List\? | 过滤输入内容 | 否 | 无 | +| textInputType | TextInputType? | 输入类型 | 否 | 无 | diff --git a/doc/components/stepBar/BrnHorizontalSteps/BrnHorizontalSteps.md b/doc/components/stepBar/BrnHorizontalSteps/BrnHorizontalSteps.md index e5d627da..e280cbe9 100644 --- a/doc/components/stepBar/BrnHorizontalSteps/BrnHorizontalSteps.md +++ b/doc/components/stepBar/BrnHorizontalSteps/BrnHorizontalSteps.md @@ -13,7 +13,7 @@ group: ## 一、效果总览 - + ## 二、描述 @@ -80,7 +80,7 @@ const BrnHorizontalSteps({ ### 效果1 -![](./img/BrnMetaHorizontalSteps5.png) +![](img/BrnHorizontalSteps5.png) diff --git a/doc/components/stepBar/BrnHorizontalSteps/img/BrnMetaHorizontalSteps1.jpg b/doc/components/stepBar/BrnHorizontalSteps/img/BrnHorizontalSteps1.jpg similarity index 100% rename from doc/components/stepBar/BrnHorizontalSteps/img/BrnMetaHorizontalSteps1.jpg rename to doc/components/stepBar/BrnHorizontalSteps/img/BrnHorizontalSteps1.jpg diff --git a/doc/components/stepBar/BrnHorizontalSteps/img/BrnMetaHorizontalSteps2.jpg b/doc/components/stepBar/BrnHorizontalSteps/img/BrnHorizontalSteps2.jpg similarity index 100% rename from doc/components/stepBar/BrnHorizontalSteps/img/BrnMetaHorizontalSteps2.jpg rename to doc/components/stepBar/BrnHorizontalSteps/img/BrnHorizontalSteps2.jpg diff --git a/doc/components/stepBar/BrnHorizontalSteps/img/BrnMetaHorizontalSteps3.jpg b/doc/components/stepBar/BrnHorizontalSteps/img/BrnHorizontalSteps3.jpg similarity index 100% rename from doc/components/stepBar/BrnHorizontalSteps/img/BrnMetaHorizontalSteps3.jpg rename to doc/components/stepBar/BrnHorizontalSteps/img/BrnHorizontalSteps3.jpg diff --git a/doc/components/stepBar/BrnHorizontalSteps/img/BrnMetaHorizontalSteps4.jpg b/doc/components/stepBar/BrnHorizontalSteps/img/BrnHorizontalSteps4.jpg similarity index 100% rename from doc/components/stepBar/BrnHorizontalSteps/img/BrnMetaHorizontalSteps4.jpg rename to doc/components/stepBar/BrnHorizontalSteps/img/BrnHorizontalSteps4.jpg diff --git a/doc/components/stepBar/BrnHorizontalSteps/img/BrnMetaHorizontalSteps5.png b/doc/components/stepBar/BrnHorizontalSteps/img/BrnHorizontalSteps5.png similarity index 100% rename from doc/components/stepBar/BrnHorizontalSteps/img/BrnMetaHorizontalSteps5.png rename to doc/components/stepBar/BrnHorizontalSteps/img/BrnHorizontalSteps5.png diff --git a/doc/components/switchButton/BrnSwitchButton.md b/doc/components/switchButton/BrnSwitchButton.md new file mode 100644 index 00000000..ad5882a8 --- /dev/null +++ b/doc/components/switchButton/BrnSwitchButton.md @@ -0,0 +1,91 @@ +--- +title: BrnSwitchButton +group: + title: Button + order: 5 +--- + +# BrnBigMainButton + +## 一、效果总览 + + + +## 二、描述 + +### 适用场景 + +常用于选项开关 + + +## 三、构造函数及参数说明 + +### 构造函数 + +```dart + BrnSwitchButton({ + Key? key, + required this.value, + this.enabled = true, + required this.onChanged, + this.size = const Size(42, 26), + this.borderColor, + }) : super(key: key); +``` +### 参数说明 + +| **参数名** | **参数类型** | 描述 | **是否必填** | **默认值** | +| --- | --- | --- | --- | --- | +| value | bool | 选中的状态 | 是 | 无 | +| enabled | bool | 是否可以交互 | 否 | true | +| onChanged | ValueChanged | 点击事件 | 否 | 无 | +| borderColor | Color? | 未选中时边框的颜色 | 否 | 主题色 | + + + +## 四、代码演示 + +### 效果1 + + + +```dart +BrnSwitchButton( + enabled: false, + value: value2, + onChanged: (value) { + setState(() { + value2 = value; + }); + }, +) +``` + + +### 效果2 + +![](./img/BrnSwitchButtonNomal.png) + +```dart +BrnSwitchButton( + value: value1, + onChanged: (value) { + setState(() { + value1 = value; + }); + }, +) +``` + +### 效果3 + +![](./img/BrnSwitchButtonOffDisable.png) + +```dart +//置灰效果 无法点击 +BrnSwitchButton( + enabled: false, + value: false, + onChanged: (value) {}, +) +``` \ No newline at end of file diff --git a/doc/components/switchButton/img/BrnSwitchButtonDisable.png b/doc/components/switchButton/img/BrnSwitchButtonDisable.png new file mode 100644 index 00000000..c94816e0 Binary files /dev/null and b/doc/components/switchButton/img/BrnSwitchButtonDisable.png differ diff --git a/doc/components/switchButton/img/BrnSwitchButtonExample.png b/doc/components/switchButton/img/BrnSwitchButtonExample.png new file mode 100644 index 00000000..2b4db7d7 Binary files /dev/null and b/doc/components/switchButton/img/BrnSwitchButtonExample.png differ diff --git a/doc/components/switchButton/img/BrnSwitchButtonNomal.png b/doc/components/switchButton/img/BrnSwitchButtonNomal.png new file mode 100644 index 00000000..d3ad04a4 Binary files /dev/null and b/doc/components/switchButton/img/BrnSwitchButtonNomal.png differ diff --git a/doc/components/switchButton/img/BrnSwitchButtonOffDisable.png b/doc/components/switchButton/img/BrnSwitchButtonOffDisable.png new file mode 100644 index 00000000..aeeefd2b Binary files /dev/null and b/doc/components/switchButton/img/BrnSwitchButtonOffDisable.png differ diff --git a/doc/components/switchButton/img/BrnSwitchButtonSize.png b/doc/components/switchButton/img/BrnSwitchButtonSize.png new file mode 100644 index 00000000..f8b7ed19 Binary files /dev/null and b/doc/components/switchButton/img/BrnSwitchButtonSize.png differ diff --git a/doc/components/switchButton/img/BrnSwitchButtonUnSelect.png b/doc/components/switchButton/img/BrnSwitchButtonUnSelect.png new file mode 100644 index 00000000..87920ef9 Binary files /dev/null and b/doc/components/switchButton/img/BrnSwitchButtonUnSelect.png differ diff --git a/doc/components/tabbar/BrnTabBar/BrnTabBar.md b/doc/components/tabbar/BrnTabBar/BrnTabBar.md index d4e558ae..76c0b3d6 100644 --- a/doc/components/tabbar/BrnTabBar/BrnTabBar.md +++ b/doc/components/tabbar/BrnTabBar/BrnTabBar.md @@ -65,8 +65,12 @@ BrnTabBar({ this.tagSpacing, this.preLineTagCount, this.tagHeight, -}) : assert(tabs == null || tabs is List) { +}) : assert(tabs != null) { this.themeData ??= BrnTabBarConfig(); + this.themeData = BrnThemeConfigurator.instance + .getConfig(configId: this.themeData!.configId) + .tabBarConfig + .merge(this.themeData); this.themeData = this.themeData!.merge(BrnTabBarConfig( tabHeight: tabHeight, indicatorHeight: indicatorWeight, @@ -77,10 +81,6 @@ BrnTabBar({ preLineTagCount: preLineTagCount, tagHeight: tagHeight, )); - this.themeData = BrnThemeConfigurator.instance - .getConfig(configId: this.themeData!.configId) - .tabBarConfig - .merge(this.themeData); } ``` diff --git a/doc/components/tag/BrnSelectTag/BrnSelectTag.md b/doc/components/tag/BrnSelectTag/BrnSelectTag.md index 8ffca7df..6365f454 100644 --- a/doc/components/tag/BrnSelectTag/BrnSelectTag.md +++ b/doc/components/tag/BrnSelectTag/BrnSelectTag.md @@ -58,6 +58,10 @@ BrnSelectTag({ assert(initTagState == null || (initTagState!.length <= 1)); } this.themeData ??= BrnTagConfig(); + this.themeData = BrnThemeConfigurator.instance + .getConfig(configId: this.themeData!.configId) + .tagConfig + .merge(this.themeData); this.themeData = this.themeData!.merge(BrnTagConfig( tagBackgroundColor: this.tagBackgroundColor, tagTextStyle: BrnTextStyle.withStyle(this.tagTextStyle), @@ -65,10 +69,6 @@ BrnSelectTag({ tagWidth: this.tagWidth, tagHeight: this.tagHeight, selectedTagBackgroundColor: this.selectedTagBackgroundColor)); - this.themeData = BrnThemeConfigurator.instance - .getConfig(configId: this.themeData!.configId) - .tagConfig - .merge(this.themeData); } ``` diff --git a/doc/components/tag/BrnStateTag/BrnStateTag.md b/doc/components/tag/BrnStateTag/BrnStateTag.md index a1ac1c18..b8671b21 100644 --- a/doc/components/tag/BrnStateTag/BrnStateTag.md +++ b/doc/components/tag/BrnStateTag/BrnStateTag.md @@ -9,7 +9,7 @@ group: ## 一、效果总览 -![](./img/BrnMetaStateTagIntro.png) +![](img/BrnStateTagIntro.png) ## 二、描述 @@ -58,7 +58,7 @@ enum TagState { ### 效果 1 - + ```dart BrnStateTag( diff --git a/doc/components/tag/BrnStateTag/img/BrnMetaStateTagIntro.png b/doc/components/tag/BrnStateTag/img/BrnStateTagIntro.png similarity index 100% rename from doc/components/tag/BrnStateTag/img/BrnMetaStateTagIntro.png rename to doc/components/tag/BrnStateTag/img/BrnStateTagIntro.png diff --git a/doc/components/tag/BrnStateTag/img/BrnMetaStateTagSucceed.png b/doc/components/tag/BrnStateTag/img/BrnStateTagSucceed.png similarity index 100% rename from doc/components/tag/BrnStateTag/img/BrnMetaStateTagSucceed.png rename to doc/components/tag/BrnStateTag/img/BrnStateTagSucceed.png diff --git a/doc/components/tag/BrnTagCustom/BrnTagCustom.md b/doc/components/tag/BrnTagCustom/BrnTagCustom.md index 0dbae402..2417f9dc 100644 --- a/doc/components/tag/BrnTagCustom/BrnTagCustom.md +++ b/doc/components/tag/BrnTagCustom/BrnTagCustom.md @@ -50,7 +50,7 @@ BrnTagCustom({ | textPadding | EdgetInsets | 标签文字的 padding | 否 | EdgeInsets.symmetric(horizontal:2) | | fontSize | double | 标签文字的大小 | 否 | 11 | | fontWeight | FontWeight | 文字的粗细 | 否 | FontWeight.normal | -| maxWidth | Double | 标签高度 | 否 | double.infinity | +| maxWidth | Double | 标签宽度 | 否 | double.infinity | | border | Border? | 标签边框 | 否 | 无 | ## 四、代码演示 diff --git a/doc/components/text/BrnEnhanceNumberCard/BrnEnhanceNumberCard.md b/doc/components/text/BrnEnhanceNumberCard/BrnEnhanceNumberCard.md index 3554fab2..08d9ad6a 100644 --- a/doc/components/text/BrnEnhanceNumberCard/BrnEnhanceNumberCard.md +++ b/doc/components/text/BrnEnhanceNumberCard/BrnEnhanceNumberCard.md @@ -24,7 +24,7 @@ group: ### **注意事项** -1、需要强化的信息,必须是非中文(BrnMetaNumberInfoItemModel的number 字段),否则会显示异常,如下所示: +1、需要强化的信息,必须是非中文(BrnNumberInfoItemModel的number 字段),否则会显示异常,如下所示: ![image-20211031145233093](./img/BrnEnhanceNumberCardIntro1.png) @@ -69,9 +69,9 @@ BrnEnhanceNumberCard({ ![image-20211031143416320](./img/BrnEnhanceNumberCardDemo1.png) ```dart -BrnMetaNumberInfoWidget( +BrnEnhanceNumberCard( itemChildren: [ - BrnMetaNumberInfoItemModel( + BrnNumberInfoItemModel( title: '数字信息', number: '3', ) @@ -106,14 +106,14 @@ BrnEnhanceNumberCard( ```dart -BrnMetaNumberInfoWidget( +BrnEnhanceNumberCard( rowCount: 2, itemChildren: [ - BrnMetaNumberInfoItemModel( + BrnNumberInfoItemModel( title: '文案信息', number: '24', ), - BrnMetaNumberInfoItemModel( + BrnNumberInfoItemModel( title: '文案信息', number: '180', ), diff --git a/doc/components/text/BrnPairInfoTable/BrnPairInfoTable.md b/doc/components/text/BrnPairInfoTable/BrnPairInfoTable.md index c0dbbc63..9fbb6c43 100644 --- a/doc/components/text/BrnPairInfoTable/BrnPairInfoTable.md +++ b/doc/components/text/BrnPairInfoTable/BrnPairInfoTable.md @@ -31,8 +31,9 @@ BrnPairInfoTable({ this.rowDistance, this.itemSpacing, this.isFolded = true, - this.themeData, + this.onExpanded, this.customKeyWidth, + this.themeData }); ``` @@ -47,6 +48,7 @@ BrnPairInfoTable({ | rowDistance | double? | 行与行之间的间距 | 否 | 4 | | itemSpacing | double? | key-value 之间的间距 | 否 | 2 | | isFolded | true | 初始的展开收起状态 | 否 | bool | +| onExpanded | ValueChanged\? | 展开手气状态变化的回调 | 否 | 无 | | customKeyWidth | TableColumnWidth? | 对齐情况下,自定义的key展示规则,默认是最大的Key展示长度是107,可以参考[_MaxWrapTableWidth]实现自定义的展示规则,指定长度等 | 否 | key 最大宽度 94 | | themeData | BrnPairInfoTableConfig? | 主题定制属性 | 否 | | diff --git a/doc/components/title/BrnCommonCardTitle/BrnCommonCardTitle.md b/doc/components/title/BrnCommonCardTitle/BrnCommonCardTitle.md index 3b4f7453..5107737c 100644 --- a/doc/components/title/BrnCommonCardTitle/BrnCommonCardTitle.md +++ b/doc/components/title/BrnCommonCardTitle/BrnCommonCardTitle.md @@ -35,24 +35,28 @@ BrnCommonCardTitle( this.detailColor, this.alignment, this.padding, + this.titleMaxLines, + this.titleOverflow = TextOverflow.clip, this.themeData}) : super(key: key); ``` ### 参数说明 -| **参数名** | **参数类型** | **描述** | **是否必填** | **默认值** | -| ---------------- | --------------------- | ----------------------------------- | ------------ | ----------------- | -| title | String | 标题文本 | 是 | | -| subTitleWidget | Widget? | 标题右侧的显示 widget | 否 | | -| accessoryText | String? | 最右侧的文字 | 否 | | -| accessoryWidget | Widget? | 最右侧的 widget | 否 | | -| onTap | VoidCallback? | 整个标题点击的事件 | 否 | | -| detailTextString | String? | 标题下面的文字 | 否 | | -| detailColor | Color? | 标题下方文字颜色 | 否 | Color(0xFF222222) | -| alignment | PlaceholderAlignment? | title 的流式文本的对齐方式 | 否 | | -| padding | EdgeInsetsGeometry? | 内容的间距 | 否 | | -| themeData | BrnCardTitleConfig? | 标题配置,详情见 BrnCardTitleConfig | 否 | | +| **参数名** | **参数类型** | **描述** | **是否必填** | **默认值** | +| ---------------- | --------------------- | ------------------------------------------------------------ | ------------ | ----------------- | +| title | String | 标题文本 | 是 | | +| subTitleWidget | Widget? | 标题右侧的显示 widget | 否 | | +| accessoryText | String? | 最右侧的文字 | 否 | | +| accessoryWidget | Widget? | 最右侧的 widget | 否 | | +| onTap | VoidCallback? | 整个标题点击的事件 | 否 | | +| detailTextString | String? | 标题下面的文字 | 否 | | +| detailColor | Color? | 标题下方文字颜色 | 否 | Color(0xFF222222) | +| alignment | PlaceholderAlignment? | title 的流式文本的对齐方式 | 否 | | +| padding | EdgeInsetsGeometry? | 内容的间距 | 否 | | +| titleMaxLines | int? | 标题最大行数 | 否 | 无 | +| titleOverflow | TextOverflow | 标题 Overflow 展示方式,
注意,由于 subTitleWidget 与 title 是流式布局,所以 subTitleWidget 会折叠 | 否 | TextOverflow.clip | +| themeData | BrnCardTitleConfig? | 标题配置,详情见 BrnCardTitleConfig | 否 | | ## 四、代码演示 @@ -63,10 +67,13 @@ BrnCommonCardTitle( ```dart BrnCommonCardTitle( title: '非箭头Title', - accessoryWidget: BrnMetaStateTag(tagText: '状态标签'), - subTitleWidget: BrnMetaStartRatingIndicator(rating: 4), + accessoryWidget: BrnStateTag(tagText: '状态标签'), + subTitleWidget: BrnRatingStar( + count: 4, + selectedCount: 2, + ), onTap: () { - BrnToast.show('BrnMetaPlainCardTitle is clicked', context); + BrnToast.show('BrnPlainCardTitle is clicked', context); }, ) ``` @@ -78,13 +85,15 @@ BrnCommonCardTitle( ```dart BrnCommonCardTitle( title: '非箭头Title', - accessoryWidget: BrnMetaStateTag(tagText: '状态标签'), - subTitleWidget: BrnMetaStartRatingIndicator(rating: 4), - detailTextString: '副标题副标题副标题', + accessoryWidget: BrnStateTag(tagText: '状态标签'), + subTitleWidget: BrnRatingStar( + count: 4, + selectedCount: 2, + ), onTap: () { - BrnToast.show('BrnMetaPlainCardTitle is clicked', context); + BrnToast.show('BrnPlainCardTitle is clicked', context); }, -) +), ``` ### 效果 3:标题和副文本 @@ -96,7 +105,7 @@ BrnCommonCardTitle( title: '非箭头Title', accessoryText: '辅助文本', onTap: () { - BrnToast.show('BrnMetaPlainCardTitle is clicked', context); + BrnToast.show('BrnPlainCardTitle is clicked', context); }, ) ``` diff --git a/doc/theme.md b/doc/theme.md index c6bf0f39..a569b59c 100644 --- a/doc/theme.md +++ b/doc/theme.md @@ -113,6 +113,6 @@ BrnMultiChoiceInputFormItem( subTitle: "这里是副标题", tipLabel: "标签", ... - themeData: BrnFormItemV2Config(titleTextStyle:BrnTextStyle(color: Colors.red)), + themeData: BrnFormItemConfig(titleTextStyle:BrnTextStyle(color: Colors.red)), ) ``` diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle index c36a549e..749c220f 100644 --- a/example/android/app/build.gradle +++ b/example/android/app/build.gradle @@ -22,20 +22,30 @@ if (flutterVersionName == null) { } apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" android { - compileSdkVersion 28 + compileSdkVersion flutter.compileSdkVersion - lintOptions { - disable 'InvalidPackage' + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlinOptions { + jvmTarget = '1.8' + } + + sourceSets { + main.java.srcDirs += 'src/main/kotlin' } defaultConfig { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "com.beike.bruno" - minSdkVersion 21 - targetSdkVersion 28 + minSdkVersion flutter.minSdkVersion + targetSdkVersion flutter.targetSdkVersion versionCode flutterVersionCode.toInteger() versionName flutterVersionName } @@ -54,5 +64,5 @@ flutter { } dependencies { - implementation 'androidx.appcompat:appcompat:1.0.0' + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" } diff --git a/example/android/app/src/debug/AndroidManifest.xml b/example/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 00000000..d06bf725 --- /dev/null +++ b/example/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/example/android/app/src/main/AndroidManifest.xml b/example/android/app/src/main/AndroidManifest.xml index c642e689..b049f539 100644 --- a/example/android/app/src/main/AndroidManifest.xml +++ b/example/android/app/src/main/AndroidManifest.xml @@ -1,45 +1,34 @@ - - - - - - - - - - - - - - - - - - - + package="com.example.bruno"> + + + + + + + + + + + + diff --git a/example/android/app/src/main/java/com/example/example/MainActivity.java b/example/android/app/src/main/java/com/example/example/MainActivity.java deleted file mode 100644 index b55ae6e0..00000000 --- a/example/android/app/src/main/java/com/example/example/MainActivity.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.example.example; - -import android.os.Bundle; -import io.flutter.app.FlutterActivity; -import io.flutter.plugins.GeneratedPluginRegistrant; - -public class MainActivity extends FlutterActivity { - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } -} diff --git a/example/android/app/src/main/kotlin/com/example/bruno/MainActivity.kt b/example/android/app/src/main/kotlin/com/example/bruno/MainActivity.kt new file mode 100644 index 00000000..03c56933 --- /dev/null +++ b/example/android/app/src/main/kotlin/com/example/bruno/MainActivity.kt @@ -0,0 +1,6 @@ +package com.example.bruno + +import io.flutter.embedding.android.FlutterActivity + +class MainActivity: FlutterActivity() { +} diff --git a/example/android/app/src/main/res/drawable-v21/launch_background.xml b/example/android/app/src/main/res/drawable-v21/launch_background.xml new file mode 100644 index 00000000..f74085f3 --- /dev/null +++ b/example/android/app/src/main/res/drawable-v21/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/example/android/app/src/main/res/values-night/styles.xml b/example/android/app/src/main/res/values-night/styles.xml new file mode 100644 index 00000000..3db14bb5 --- /dev/null +++ b/example/android/app/src/main/res/values-night/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/example/android/app/src/main/res/values/styles.xml b/example/android/app/src/main/res/values/styles.xml index c745a5ef..d460d1e9 100644 --- a/example/android/app/src/main/res/values/styles.xml +++ b/example/android/app/src/main/res/values/styles.xml @@ -1,11 +1,18 @@ - - diff --git a/example/android/app/src/profile/AndroidManifest.xml b/example/android/app/src/profile/AndroidManifest.xml new file mode 100644 index 00000000..d06bf725 --- /dev/null +++ b/example/android/app/src/profile/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/example/android/build.gradle b/example/android/build.gradle index bb8a3038..4256f917 100644 --- a/example/android/build.gradle +++ b/example/android/build.gradle @@ -1,18 +1,20 @@ buildscript { + ext.kotlin_version = '1.6.10' repositories { google() - jcenter() + mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:3.2.1' + classpath 'com.android.tools.build:gradle:4.1.0' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } allprojects { repositories { google() - jcenter() + mavenCentral() } } diff --git a/example/android/gradle.properties b/example/android/gradle.properties index a5965ab8..4d3226ab 100644 --- a/example/android/gradle.properties +++ b/example/android/gradle.properties @@ -1,4 +1,3 @@ org.gradle.jvmargs=-Xmx1536M -android.enableR8=true android.useAndroidX=true android.enableJetifier=true \ No newline at end of file diff --git a/example/android/gradle/wrapper/gradle-wrapper.properties b/example/android/gradle/wrapper/gradle-wrapper.properties index 2819f022..bc6a58af 100644 --- a/example/android/gradle/wrapper/gradle-wrapper.properties +++ b/example/android/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip diff --git a/example/android/settings.gradle b/example/android/settings.gradle index 5a2f14fb..44e62bcf 100644 --- a/example/android/settings.gradle +++ b/example/android/settings.gradle @@ -1,15 +1,11 @@ include ':app' -def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() +def localPropertiesFile = new File(rootProject.projectDir, "local.properties") +def properties = new Properties() -def plugins = new Properties() -def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') -if (pluginsFile.exists()) { - pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } -} +assert localPropertiesFile.exists() +localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } -plugins.each { name, path -> - def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() - include ":$name" - project(":$name").projectDir = pluginDirectory -} +def flutterSdkPath = properties.getProperty("flutter.sdk") +assert flutterSdkPath != null, "flutter.sdk not set in local.properties" +apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" diff --git a/example/ios/Flutter/AppFrameworkInfo.plist b/example/ios/Flutter/AppFrameworkInfo.plist index 6b4c0f78..f2872cf4 100644 --- a/example/ios/Flutter/AppFrameworkInfo.plist +++ b/example/ios/Flutter/AppFrameworkInfo.plist @@ -21,6 +21,6 @@ CFBundleVersion 1.0 MinimumOSVersion - 8.0 + 9.0 diff --git a/example/lib/main.dart b/example/lib/main.dart index f1993428..af9a7870 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -13,7 +13,7 @@ class MyApp extends StatelessWidget { return MaterialApp( title: 'Flutter Example', theme: ThemeData( - primarySwatch: Colors.grey, + primarySwatch: Colors.blue, ), home: HomePage(), ); diff --git a/example/lib/sample/components/actionsheet/actionsheet_selected_list_example.dart b/example/lib/sample/components/actionsheet/actionsheet_selected_list_example.dart index fd68e9ca..10f04ba9 100644 --- a/example/lib/sample/components/actionsheet/actionsheet_selected_list_example.dart +++ b/example/lib/sample/components/actionsheet/actionsheet_selected_list_example.dart @@ -119,7 +119,7 @@ class SelectedListActionSheetExamplePageState onListShowed: () { BrnToast.show("显示了哦~~", context); }, - onItemDelete: (int idx, String entity) { + onItemDelete: (int idx, String? entity) { _data[idx] = '$idx 变化了哈'; controller.reloadData(); BrnToast.show("$idx 奇数行无法删除", context); diff --git a/example/lib/sample/components/bottom_tabbar/bottom_tabbar_example.dart b/example/lib/sample/components/bottom_tabbar/bottom_tabbar_example.dart index 80473add..df185807 100644 --- a/example/lib/sample/components/bottom_tabbar/bottom_tabbar_example.dart +++ b/example/lib/sample/components/bottom_tabbar/bottom_tabbar_example.dart @@ -175,6 +175,7 @@ class BottomTabbarExampleState extends State BrnBottomTabBar( fixedColor: Colors.blue, currentIndex: _selectedIndexTest2, + type: BrnBottomTabBarDisplayType.shifting, onTap: _onItemSelectedTest2, items: [ BrnBottomTabBarItem(icon: Icon(icons[0]), title: Text(titles[0])), @@ -187,6 +188,7 @@ class BottomTabbarExampleState extends State ), BrnBottomTabBar( fixedColor: Colors.blue, + type: BrnBottomTabBarDisplayType.shifting, currentIndex: _selectedIndexTest3, onTap: _onItemSelectedTest3, items: _getTabBarItems(count: 8), diff --git a/example/lib/sample/components/card/bubble/bubble_entry_page.dart b/example/lib/sample/components/card/bubble/bubble_entry_page.dart index 139d169c..618e1fdc 100644 --- a/example/lib/sample/components/card/bubble/bubble_entry_page.dart +++ b/example/lib/sample/components/card/bubble/bubble_entry_page.dart @@ -4,7 +4,6 @@ import 'package:bruno/bruno.dart'; import 'package:example/sample/components/card/bubble/common_bubble_example.dart'; import 'package:example/sample/components/card/bubble/brn_expanded_bubble_example.dart'; import 'package:example/sample/home/list_item.dart'; -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; class BubbleEntryPage extends StatelessWidget { diff --git a/example/lib/sample/components/card/content/text_content_entry_page.dart b/example/lib/sample/components/card/content/text_content_entry_page.dart index a38c6a4b..938931c6 100644 --- a/example/lib/sample/components/card/content/text_content_entry_page.dart +++ b/example/lib/sample/components/card/content/text_content_entry_page.dart @@ -9,7 +9,6 @@ import 'package:example/sample/components/card/content/brn_two_rich_content_exam import 'package:example/sample/components/card/content/brn_two_text_content_example.dart'; import 'package:example/sample/components/card/content/brn_two_text_expanded_example.dart'; import 'package:example/sample/home/list_item.dart'; -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; class TextContentEntryPage extends StatelessWidget { diff --git a/example/lib/sample/components/card_title/brn_common_title_example.dart b/example/lib/sample/components/card_title/brn_common_title_example.dart index fd5bd176..7b8589dd 100644 --- a/example/lib/sample/components/card_title/brn_common_title_example.dart +++ b/example/lib/sample/components/card_title/brn_common_title_example.dart @@ -45,6 +45,11 @@ class _BrnCommonTitleExampleState extends State { ), BrnCommonCardTitle( title: '非箭头Title', + accessoryWidget: BrnStateTag(tagText: '状态标签'), + subTitleWidget: BrnRatingStar( + count: 2, + selectedCount: 2, + ), onTap: () { BrnToast.show('BrnPlainCardTitle is clicked', context); }, diff --git a/example/lib/sample/components/charts/progress_bar_chart_example.dart b/example/lib/sample/components/charts/progress_bar_chart_example.dart index 0baa6afb..72ac818f 100644 --- a/example/lib/sample/components/charts/progress_bar_chart_example.dart +++ b/example/lib/sample/components/charts/progress_bar_chart_example.dart @@ -1,5 +1,3 @@ - - import 'dart:math'; import 'package:bruno/bruno.dart'; import 'package:flutter/material.dart'; @@ -25,104 +23,114 @@ class ProgressBarChartExampleState extends State { appBar: BrnAppBar( title: '柱状图', ), - body: Column( - children: [ - BrnProgressBarChart( - barChartStyle: BarChartStyle.horizontal, - xAxis: ChartAxis(axisItemList: [ - AxisItem(showText: '10'), - AxisItem(showText: '20'), - AxisItem(showText: '30') - ]), - yAxis: ChartAxis(axisItemList: [ - AxisItem(showText: '示例1'), - AxisItem(showText: '示例2') - ]), - singleBarWidth: 30, - barBundleList: [ - BrnProgressBarBundle(barList: [ - BrnProgressBarItem(text: '示例', value: 10, hintValue: 15), - BrnProgressBarItem(text: '示例', value: 20) - ], colors: [ - Color(0xff1545FD), - Color(0xff0984F9) + body: SingleChildScrollView( + child: Column( + children: [ + BrnProgressBarChart( + barChartStyle: BarChartStyle.horizontal, + xAxis: ChartAxis(axisItemList: [ + AxisItem(showText: '1010'), + AxisItem(showText: '20'), + AxisItem(showText: '30'), + AxisItem(showText: '40'), + AxisItem(showText: '50'), + AxisItem(showText: '60'), + AxisItem(showText: '70'), + ]), + yAxis: ChartAxis(axisItemList: [ + AxisItem(showText: '示例1'), + AxisItem(showText: '示例2'), + AxisItem(showText: '示例3'), + AxisItem(showText: '示例4'), + AxisItem(showText: '示例5'), ]), - ], - ), - BrnProgressBarChart( - barChartStyle: BarChartStyle.vertical, - xAxis: ChartAxis(axisItemList: [ - AxisItem(showText: '示例1'), - AxisItem(showText: '示例2'), - AxisItem(showText: '示例3'), - AxisItem(showText: '示例4'), - AxisItem(showText: '示例5'), - AxisItem(showText: '示例6'), - AxisItem(showText: '示例7'), - AxisItem(showText: '示例8'), - AxisItem(showText: '示例9'), - AxisItem(showText: '示例10'), - ]), - barBundleList: [ - BrnProgressBarBundle(barList: [ - BrnProgressBarItem( - text: '示例11', - value: 5, - hintValue: 15, - showBarValueText: "1122334"), - BrnProgressBarItem( - text: '示例12', value: 20, selectedHintText: '示例12:20'), - BrnProgressBarItem( - text: '示例13', - value: 30, - selectedHintText: - '示例13:30\n示例13:30\n示例13:30\n示例13:30\n示例13:30\n示例13:30'), - BrnProgressBarItem(text: '示例14', value: 25), - BrnProgressBarItem(text: '示例15', value: 21), - BrnProgressBarItem(text: '示例16', value: 28), - BrnProgressBarItem(text: '示例17', value: 15), - BrnProgressBarItem(text: '示例18', value: 11), - BrnProgressBarItem(text: '示例19', value: 30), - BrnProgressBarItem(text: '示例110', value: 24), - ], colors: [ - Color(0xff1545FD), - Color(0xff0984F9) + singleBarWidth: 30, + barBundleList: [ + BrnProgressBarBundle(barList: [ + BrnProgressBarItem(text: '示例', value: 10, hintValue: 15), + BrnProgressBarItem(text: '示例', value: 20), + BrnProgressBarItem(text: '示例', value: 30, hintValue: 15), + BrnProgressBarItem(text: '示例', value: 20, hintValue: 15), + BrnProgressBarItem(text: '示例', value: 0, hintValue: 15), + ], colors: [ + Color(0xff1545FD), + Color(0xff0984F9) + ]), + ], + barChartSelectCallback: (BrnProgressBarItem? barItem) { + BrnToast.show(barItem?.text ?? '', context); + }, + ), + BrnProgressBarChart( + barChartStyle: BarChartStyle.vertical, + xAxis: ChartAxis(axisItemList: [ + AxisItem(showText: '示例1'), + AxisItem(showText: '示例2'), + AxisItem(showText: '示例3'), + AxisItem(showText: '示例4'), + AxisItem(showText: '示例5'), + AxisItem(showText: '示例6'), + AxisItem(showText: '示例7'), + AxisItem(showText: '示例8'), + AxisItem(showText: '示例9'), + AxisItem(showText: '示例10'), ]), - BrnProgressBarBundle(barList: [ - BrnProgressBarItem(text: '示例21', value: 20, hintValue: 15), - BrnProgressBarItem( - text: '示例22', value: 15, selectedHintText: '示例12:20'), - BrnProgressBarItem( - text: '示例23', - value: 30, - selectedHintText: - '示例13:30\n示例13:30\n示例13:30\n示例13:30\n示例13:30\n示例13:30'), - BrnProgressBarItem(text: '示例24', value: 20), - BrnProgressBarItem(text: '示例25', value: 28), - BrnProgressBarItem(text: '示例26', value: 25), - BrnProgressBarItem(text: '示例27', value: 17), - BrnProgressBarItem(text: '示例28', value: 14), - BrnProgressBarItem(text: '示例29', value: 36), - BrnProgressBarItem(text: '示例210', value: 29), - ], colors: [ - Color(0xff01D57D), - Color(0xff01D57D) + barBundleList: [ + BrnProgressBarBundle(barList: [ + BrnProgressBarItem( + text: '示例11', value: 5, hintValue: 15, showBarValueText: "1122334"), + BrnProgressBarItem(text: '示例12', value: 20, selectedHintText: '示例12:20'), + BrnProgressBarItem( + text: '示例13', + value: 30, + selectedHintText: '示例13:30\n示例13:30\n示例13:30\n示例13:30\n示例13:30\n示例13:30'), + BrnProgressBarItem(text: '示例14', value: 25), + BrnProgressBarItem(text: '示例15', value: 21), + BrnProgressBarItem(text: '示例16', value: 28), + BrnProgressBarItem(text: '示例17', value: 15), + BrnProgressBarItem(text: '示例18', value: 11), + BrnProgressBarItem(text: '示例19', value: 30), + BrnProgressBarItem(text: '示例110', value: 24), + ], colors: [ + Color(0xff1545FD), + Color(0xff0984F9) + ]), + BrnProgressBarBundle(barList: [ + BrnProgressBarItem(text: '示例21', value: 20, hintValue: 15), + BrnProgressBarItem(text: '示例22', value: 15, selectedHintText: '示例12:20'), + BrnProgressBarItem( + text: '示例23', + value: 30, + selectedHintText: '示例13:30\n示例13:30\n示例13:30\n示例13:30\n示例13:30\n示例13:30'), + BrnProgressBarItem(text: '示例24', value: 20), + BrnProgressBarItem(text: '示例25', value: 28), + BrnProgressBarItem(text: '示例26', value: 25), + BrnProgressBarItem(text: '示例27', value: 17), + BrnProgressBarItem(text: '示例28', value: 14), + BrnProgressBarItem(text: '示例29', value: 36), + BrnProgressBarItem(text: '示例210', value: 29), + ], colors: [ + Color(0xff01D57D), + Color(0xff01D57D) + ]), + ], + yAxis: ChartAxis(axisItemList: [ + AxisItem(showText: '10'), + AxisItem(showText: '20'), + AxisItem(showText: '30') ]), - ], - yAxis: ChartAxis(axisItemList: [ - AxisItem(showText: '10'), - AxisItem(showText: '20'), - AxisItem(showText: '30') - ]), - singleBarWidth: 30, - barGroupSpace: 30, - barMaxValue: 60, - onBarItemClickInterceptor: - (barBundleIndex, barBundle, barGroupIndex, barItem) { - return true; - }, - ) - ], + singleBarWidth: 30, + barGroupSpace: 30, + barMaxValue: 60, + onBarItemClickInterceptor: (barBundleIndex, barBundle, barGroupIndex, barItem) { + return true; + }, + barChartSelectCallback: (BrnProgressBarItem? barItem) { + BrnToast.show(barItem?.text ?? '', context); + }, + ) + ], + ), ), ); } diff --git a/example/lib/sample/components/dialog/dialog_entry_page.dart b/example/lib/sample/components/dialog/dialog_entry_page.dart index a4be831e..704f85bd 100644 --- a/example/lib/sample/components/dialog/dialog_entry_page.dart +++ b/example/lib/sample/components/dialog/dialog_entry_page.dart @@ -533,7 +533,7 @@ class DialogEntryPage extends StatelessWidget { hintText: '提示信息', cancelText: '取消', confirmText: '确定', - maxLength: 100, + maxLength: 10, barrierDismissible: false, textInputAction: TextInputAction.done, onConfirm: (value) { diff --git a/example/lib/sample/components/form/all_item_style_example.dart b/example/lib/sample/components/form/all_item_style_example.dart index 07630cad..2e17f930 100644 --- a/example/lib/sample/components/form/all_item_style_example.dart +++ b/example/lib/sample/components/form/all_item_style_example.dart @@ -1,5 +1,3 @@ - - import 'package:bruno/bruno.dart'; import 'package:example/sample/components/form/group_example/expansion_group_example.dart'; import 'package:example/sample/components/form/group_example/group_add_example.dart'; @@ -14,12 +12,14 @@ import 'package:example/sample/components/form/items_example/ratio_input_example import 'package:example/sample/components/form/items_example/select_all_title_example.dart'; import 'package:example/sample/components/form/items_example/star_example.dart'; import 'package:example/sample/components/form/items_example/step_input_example.dart'; +import 'package:example/sample/components/form/items_example/switch_example.dart'; import 'package:example/sample/components/form/items_example/text_block_input_example.dart'; import 'package:example/sample/components/form/items_example/text_input_example.dart'; import 'package:example/sample/components/form/items_example/text_quick_select_input_example.dart'; import 'package:example/sample/components/form/items_example/text_select_example.dart'; import 'package:example/sample/components/form/items_example/title_example.dart'; import 'package:example/sample/components/form/items_example/title_select_example.dart'; +import 'package:example/sample/components/form/items_example/general_item_example.dart'; import 'package:example/sample/home/list_item.dart'; import 'package:flutter/material.dart'; @@ -45,8 +45,38 @@ class AllFormItemStyleExamplePage extends StatelessWidget { Widget getBodyWidget(BuildContext context) { return ListView( children: [ + ListItem( - title: "选择类型: 2种", + title: "基础类型 ", + titleFontSize: 22, + titleColor: Colors.red, + ), + ListItem( + title: "基础标题表单项", + describe: "基础类型", + isSupportTheme: true, + onPressed: () { + Navigator.push(context, MaterialPageRoute( + builder: (BuildContext context) { + return BaseTitleExamplePage("标题表单项"); + }, + )); + }, + ), + ListItem( + title: "基础通用表单项", + describe: "自定义基础表单", + isSupportTheme: true, + onPressed: () { + Navigator.push(context, MaterialPageRoute( + builder: (BuildContext context) { + return GeneralFormExamplePage("自定义基础表单"); + }, + )); + }, + ), + ListItem( + title: "选择类型", titleFontSize: 22, titleColor: Colors.red, ), @@ -198,61 +228,61 @@ class AllFormItemStyleExamplePage extends StatelessWidget { titleColor: Colors.red, ), ListItem( - title: "基础标题表单项", + title: "标题表单项", describe: "杂项类型", isSupportTheme: true, onPressed: () { Navigator.push(context, MaterialPageRoute( builder: (BuildContext context) { - return BaseTitleExamplePage("标题表单项"); + return TitleExamplePage("标题表单项"); }, )); }, ), ListItem( - title: "标题表单项", + title: "全选表单项", describe: "杂项类型", isSupportTheme: true, onPressed: () { Navigator.push(context, MaterialPageRoute( builder: (BuildContext context) { - return TitleExamplePage("标题表单项"); + return SelectAllTitleExamplePage("全选表单项"); }, )); }, ), ListItem( - title: "全选表单项", - describe: "杂项类型", + title: "评星表单项", + describe: '各种形态', isSupportTheme: true, onPressed: () { Navigator.push(context, MaterialPageRoute( builder: (BuildContext context) { - return SelectAllTitleExamplePage("全选表单项"); + return StarInputExamplePage("评星表单项"); }, )); }, ), ListItem( - title: "评星表单项", + title: "递增表单项", describe: '各种形态', isSupportTheme: true, onPressed: () { Navigator.push(context, MaterialPageRoute( builder: (BuildContext context) { - return StarInputExamplePage("评星表单项"); + return StepInputExamplePage(title: "递增表单项"); }, )); }, ), ListItem( - title: "递增表单项", + title: "Switch表单项", describe: '各种形态', isSupportTheme: true, onPressed: () { Navigator.push(context, MaterialPageRoute( builder: (BuildContext context) { - return StepInputExamplePage("递增表单项f`ormItemConfig"); + return SwitchInputExamplePage("Switch表单项"); }, )); }, diff --git a/example/lib/sample/components/form/items_example/general_item_example.dart b/example/lib/sample/components/form/items_example/general_item_example.dart new file mode 100644 index 00000000..e4e07fa7 --- /dev/null +++ b/example/lib/sample/components/form/items_example/general_item_example.dart @@ -0,0 +1,101 @@ +import 'package:flutter/material.dart'; + +import 'package:bruno/bruno.dart'; + +class GeneralFormExamplePage extends StatelessWidget { + final String _title; + + GeneralFormExamplePage(this._title); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: BrnAppBar( + title: _title, + ), + body: ListView( + children: [ + Container( + padding: EdgeInsets.fromLTRB(20, 5, 20, 5), + child: Text( + "基本样式:", + style: TextStyle( + color: Color(0xFF222222), + fontSize: 22, + )), + ), + BrnGeneralFormItem( + title: "自然到访保护期", + subTitle: "这里是副标题", + onTip: () { + BrnToast.show("点击触发onTip回调", context); + }, + onAddTap: () { + BrnToast.show("点击触发onAddTap回调", context); + }, + onRemoveTap: () { + BrnToast.show("点击触发onRemoveTap回调", context); + }, + ), + Container( + padding: EdgeInsets.fromLTRB(20, 20, 20, 5), + child: Text( + "全功能样式:", + style: TextStyle( + color: Color(0xFF222222), + fontSize: 22, + ), + ), + ), + BrnGeneralFormItem( + prefixIconType: BrnPrefixIconType.add, + isRequire: true, + isEdit: true, + error: "必填项不能为空", + titleWidget: Text("自然到访保护期"), + subTitleWidget: Text("这里是副标题"), + tipLabel: "标签", + operateWidget: Text("右侧操作区"), + onTip: () { + BrnToast.show("点击触发onTip回调", context); + }, + onAddTap: () { + BrnToast.show("点击触发onAddTap回调", context); + }, + onRemoveTap: () { + BrnToast.show("点击触发onRemoveTap回调", context); + }, + ), + Container( + padding: EdgeInsets.fromLTRB(20, 20, 20, 5), + child: Text( + "no error:", + style: TextStyle( + color: Color(0xFF222222), + fontSize: 22, + ), + ), + ), + BrnGeneralFormItem( + prefixIconType: BrnPrefixIconType.add, + isRequire: true, + isEdit: true, + titleWidget: Text("自然到访保护期"), +// subTitleWidget: Text("这里是副标题"), + tipLabel: "标签", + operateWidget: Text("右侧操作区"), + + onTip: () { + BrnToast.show("点击触发onTip回调", context); + }, + onAddTap: () { + BrnToast.show("点击触发onAddTap回调", context); + }, + onRemoveTap: () { + BrnToast.show("点击触发onRemoveTap回调", context); + }, + ), + ], + )); + } +} diff --git a/example/lib/sample/components/form/items_example/step_input_example.dart b/example/lib/sample/components/form/items_example/step_input_example.dart index 3b828923..001c0d29 100644 --- a/example/lib/sample/components/form/items_example/step_input_example.dart +++ b/example/lib/sample/components/form/items_example/step_input_example.dart @@ -3,16 +3,24 @@ import 'package:bruno/bruno.dart'; import 'package:flutter/material.dart'; -class StepInputExamplePage extends StatelessWidget { - final String _title; +class StepInputExamplePage extends StatefulWidget { - StepInputExamplePage(this._title); + final String title; + const StepInputExamplePage({Key? key, this.title = '示例'}) : super(key: key); + + @override + State createState() => _StepInputExamplePageState(); +} + +class _StepInputExamplePageState extends State { + + TextEditingController _manualInputController = TextEditingController()..text = '23'; @override Widget build(BuildContext context) { return Scaffold( appBar: BrnAppBar( - title: _title, + title: widget.title, ), body: ListView( children: [ @@ -113,6 +121,30 @@ class StepInputExamplePage extends StatelessWidget { "点击触发回调${oldValue}_${newValue}_onChanged", context); }, ), + BrnStepInputFormItem( + prefixIconType: BrnPrefixIconType.add, + isRequire: true, + isEdit: true, + canManualInput: true, + controller: _manualInputController, + title: "可手动输入", + subTitle: "可传入 controller设置初始值 ", + maxLimit: 99, + minLimit: 0, + onTip: () { + BrnToast.show("点击触发onTip回调", context); + }, + onAddTap: () { + BrnToast.show("点击触发onAddTap回调", context); + }, + onRemoveTap: () { + BrnToast.show("点击触发onRemoveTap回调", context); + }, + onChanged: (oldValue, newValue) { + BrnToast.show( + "点击触发回调_${oldValue}_${newValue}_onChanged", context); + }, + ), ], )); } diff --git a/example/lib/sample/components/form/items_example/switch_example.dart b/example/lib/sample/components/form/items_example/switch_example.dart new file mode 100644 index 00000000..bae47be8 --- /dev/null +++ b/example/lib/sample/components/form/items_example/switch_example.dart @@ -0,0 +1,134 @@ +import 'package:bruno/bruno.dart'; +import 'package:flutter/material.dart'; + +class SwitchInputExamplePage extends StatefulWidget { + final String _title; + + SwitchInputExamplePage(this._title); + + @override + State createState() { + return SwitchInputExampleState(); + } +} + +class SwitchInputExampleState extends State{ + + bool _isFirstSwitchOn = true; + bool _isSecondSwitchOn = true; + bool _isThirdSwitchOn = true; + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: BrnAppBar( + title: widget._title, + ), + body: ListView( + children: [ + Container( + padding: EdgeInsets.fromLTRB(20, 5, 20, 5), + child: Text( + "基本样式:", + style: TextStyle( + color: Color(0xFF222222), + fontSize: 22, + ), + ), + ), + BrnSwitchFormItem( + title: "自然到访保护期", + value: _isFirstSwitchOn, + onTip: () { + BrnToast.show("点击触发onTip回调", context); + }, + onAddTap: () { + BrnToast.show("点击触发onAddTap回调", context); + }, + onRemoveTap: () { + BrnToast.show("点击触发onRemoveTap回调", context); + }, + onChanged: (oldValue, newValue) { + setState(() { + _isFirstSwitchOn = newValue; + }); + BrnToast.show( + "点击触发回调${oldValue}_${newValue}_onChanged", context); + }, + ), + Container( + padding: EdgeInsets.fromLTRB(20, 20, 20, 5), + child: Text( + "全功能样式:", + style: TextStyle( + color: Color(0xFF222222), + fontSize: 22, + ), + ), + ), + BrnSwitchFormItem( + prefixIconType: BrnPrefixIconType.add, + isRequire: true, + isEdit: true, + error: "必填项不能为空", + title: "自然到访保护期", + subTitle: "这里是副标题", + tipLabel: "标签", + value: _isSecondSwitchOn, + onTip: () { + BrnToast.show("点击触发onTip回调", context); + }, + onAddTap: () { + BrnToast.show("点击触发onAddTap回调", context); + }, + onRemoveTap: () { + BrnToast.show("点击触发onRemoveTap回调", context); + }, + onChanged: (oldValue, newValue) { + setState(() { + _isSecondSwitchOn = newValue; + }); + BrnToast.show( + "点击触发回调${oldValue}_${newValue}_onChanged", context); + }, + ), + Container( + padding: EdgeInsets.fromLTRB(20, 20, 20, 5), + child: Text( + "no error:", + style: TextStyle( + color: Color(0xFF222222), + fontSize: 22, + ), + ), + ), + BrnSwitchFormItem( + prefixIconType: BrnPrefixIconType.add, + isRequire: true, + isEdit: false, + title: "自然到访保护期", + subTitle: "这里是副标题", + tipLabel: "标签", + value: _isThirdSwitchOn, + onTip: () { + BrnToast.show("点击触发onTip回调", context); + }, + onAddTap: () { + BrnToast.show("点击触发onAddTap回调", context); + }, + onRemoveTap: () { + BrnToast.show("点击触发onRemoveTap回调", context); + }, + onChanged: (oldValue, newValue) { + setState(() { + _isThirdSwitchOn = newValue; + }); + BrnToast.show( + "点击触发回调${oldValue}_${newValue}_onChanged", context); + }, + ), + ], + )); + } + +} diff --git a/example/lib/sample/components/form/items_example/text_quick_select_input_example.dart b/example/lib/sample/components/form/items_example/text_quick_select_input_example.dart index e4a8ede0..aa3d9205 100644 --- a/example/lib/sample/components/form/items_example/text_quick_select_input_example.dart +++ b/example/lib/sample/components/form/items_example/text_quick_select_input_example.dart @@ -2,7 +2,6 @@ import 'package:bruno/bruno.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/widgets.dart'; class TextQuickSelectInputExamplePage extends StatefulWidget { final String _title; diff --git a/example/lib/sample/components/form/items_example/text_select_example.dart b/example/lib/sample/components/form/items_example/text_select_example.dart index 7a689bbd..0fccc6c9 100644 --- a/example/lib/sample/components/form/items_example/text_select_example.dart +++ b/example/lib/sample/components/form/items_example/text_select_example.dart @@ -2,7 +2,6 @@ import 'package:bruno/bruno.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/widgets.dart'; class TextSelectInputExamplePage extends StatelessWidget { final String _title; diff --git a/example/lib/sample/components/guide/guide_entry_page.dart b/example/lib/sample/components/guide/guide_entry_page.dart index 7b991338..20faacbd 100644 --- a/example/lib/sample/components/guide/guide_entry_page.dart +++ b/example/lib/sample/components/guide/guide_entry_page.dart @@ -4,7 +4,6 @@ import 'package:bruno/bruno.dart'; import 'package:example/sample/components/guide/force_guide_example.dart'; import 'package:example/sample/components/guide/soft_intro_example.dart'; import 'package:example/sample/home/list_item.dart'; -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; class GuideEntryPage extends StatelessWidget { diff --git a/example/lib/sample/components/input/input_example.dart b/example/lib/sample/components/input/input_example.dart index 1b15e211..7321205a 100644 --- a/example/lib/sample/components/input/input_example.dart +++ b/example/lib/sample/components/input/input_example.dart @@ -2,7 +2,6 @@ import 'package:bruno/bruno.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/widgets.dart'; class TextModel { String? text; diff --git a/example/lib/sample/components/picker/multi_picker_example.dart b/example/lib/sample/components/picker/multi_picker_example.dart index ad50ea05..e311a1b4 100644 --- a/example/lib/sample/components/picker/multi_picker_example.dart +++ b/example/lib/sample/components/picker/multi_picker_example.dart @@ -140,9 +140,40 @@ class MultiPickerExamplePage extends StatelessWidget { ).show(); }, ), + ListItem( + title: "默认 Delegate", + describe: '使用默认 Delegate 构造数据展示', + onPressed: () { + BrnMultiDataPicker( + context: context, + title: '来源', + delegate: BrnDefaultMultiDataPickerDelegate( + firstSelectedIndex: 2, + secondSelectedIndex: 1, + thirdSelectedIndex: 1, + data: _getDefaultDelegateData()), + confirmClick: (list) { + BrnToast.show(list.toString(), context); + }, + ).show(); + }, + ), ], )); } + + List _getDefaultDelegateData() { + BrnMultiDataPickerEntity data = BrnMultiDataPickerEntity( + text: '测试1', value: 5095791542795657, children: []); + + BrnMultiDataPickerEntity data2 = BrnMultiDataPickerEntity( + text: '测试2', value: 5029051542795656, children: []); + + BrnMultiDataPickerEntity data3 = BrnMultiDataPickerEntity( + text: '测试3', value: 5090501542795658, children: []); + + return [data, data2, data3]; + } } class Brn1RowDelegate implements BrnMultiDataPickerDelegate { diff --git a/example/lib/sample/components/scroll_anchor/scroll_actor_tab_example.dart b/example/lib/sample/components/scroll_anchor/scroll_actor_tab_example.dart index 5ac76358..c72810fb 100644 --- a/example/lib/sample/components/scroll_anchor/scroll_actor_tab_example.dart +++ b/example/lib/sample/components/scroll_anchor/scroll_actor_tab_example.dart @@ -13,14 +13,20 @@ class ScrollActorTabExample extends StatelessWidget { title: '锚点', ), body: BrnAnchorTab( - itemCount: 10, + itemCount: 20, widgetIndexedBuilder: (context, index) { - return Container( - child: Center(child: Text('$index')), - height: Random().nextInt(400).toDouble(), - color: Color.fromARGB(Random().nextInt(255), Random().nextInt(255), - Random().nextInt(255), Random().nextInt(255)), - ); + return StatefulBuilder(builder: (_, state) { + double height = Random().nextInt(400).toDouble(); + return GestureDetector(child: Container( + child: Center(child: Text('$index')), + height: height, + color: Color.fromARGB(Random().nextInt(255), Random().nextInt(255), + Random().nextInt(255), Random().nextInt(255)), + ), + onTap: (){ + state(() {}); + },); + }); }, tabIndexedBuilder: (context, index) { return BadgeTab(text: 'index $index'); diff --git a/example/lib/sample/components/step/step_example.dart b/example/lib/sample/components/step/step_example.dart index 03d7833d..7f506f22 100644 --- a/example/lib/sample/components/step/step_example.dart +++ b/example/lib/sample/components/step/step_example.dart @@ -4,7 +4,6 @@ import 'package:bruno/bruno.dart'; import 'package:example/sample/components/step/brn_horizontal_step_example.dart'; import 'package:example/sample/components/step/step_line_example.dart'; import 'package:example/sample/home/list_item.dart'; -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; class StepExample extends StatelessWidget { diff --git a/example/lib/sample/components/switch/brn_switch_example.dart b/example/lib/sample/components/switch/brn_switch_example.dart new file mode 100644 index 00000000..01f49150 --- /dev/null +++ b/example/lib/sample/components/switch/brn_switch_example.dart @@ -0,0 +1,134 @@ +import 'package:bruno/bruno.dart'; +import 'package:flutter/material.dart'; + +class BrnSwitchButtonExample extends StatefulWidget { + @override + _BrnSwitchButtonExampleState createState() => _BrnSwitchButtonExampleState(); +} + +class _BrnSwitchButtonExampleState extends State { + bool value1 = true; + bool value2 = true; + bool value3 = false; + bool value5 = true; + + @override + void initState() { + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Colors.white, + appBar: BrnAppBar( + title: '开关元件', + ), + body: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + '规则', + style: TextStyle( + color: Color(0xFF222222), + fontSize: 28, + fontWeight: FontWeight.bold), + ), + BrnBubbleText(maxLines: 2, text: '具备选中、未选中、以及禁用状态'), + Text( + '正常案例', + style: TextStyle( + color: Color(0xFF222222), + fontSize: 28, + ), + ), + Padding( + padding: const EdgeInsets.all(8.0), + child: BrnSwitchButton( + value: value1, + onChanged: (value) { + setState(() { + value1 = value; + }); + }, + ), + ), + Text( + '禁用案例', + style: TextStyle( + color: Color(0xFF222222), + fontSize: 28, + ), + ), + Padding( + padding: const EdgeInsets.all(8.0), + child: BrnSwitchButton( + enabled: false, + value: value2, + onChanged: (value) { + setState(() { + value2 = value; + }); + }, + ), + ), + Text( + '未选案例', + style: TextStyle( + color: Color(0xFF222222), + fontSize: 28, + ), + ), + Padding( + padding: const EdgeInsets.all(8.0), + child: BrnSwitchButton( + value: value3, + onChanged: (value) { + setState(() { + value3 = value; + }); + }, + ), + ), + Text( + '禁用案例', + style: TextStyle( + color: Color(0xFF222222), + fontSize: 28, + ), + ), + Padding( + padding: const EdgeInsets.all(8.0), + child: BrnSwitchButton( + enabled: false, + value: false, + onChanged: (value) {}, + ), + ), + Text( + '自定义大小', + style: TextStyle( + color: Color(0xFF222222), + fontSize: 28, + ), + ), + Padding( + padding: const EdgeInsets.all(8.0), + child: BrnSwitchButton( + size: Size(80, 40), + value: value5, + onChanged: (value) { + setState(() { + value5 = value; + }); + }, + ), + ), + ], + ), + ), + ); + } +} diff --git a/example/lib/sample/home/card_data_config.dart b/example/lib/sample/home/card_data_config.dart index e3ee0a88..e2f1d98b 100644 --- a/example/lib/sample/home/card_data_config.dart +++ b/example/lib/sample/home/card_data_config.dart @@ -38,6 +38,7 @@ import 'package:example/sample/components/scroll_anchor/scroll_actor_tab_example import 'package:example/sample/components/selection/selection_entry_page.dart'; import 'package:example/sample/components/step/step_example.dart'; import 'package:example/sample/components/sugsearch/search_text_example.dart'; +import 'package:example/sample/components/switch/brn_switch_example.dart'; import 'package:example/sample/components/switch/checkbox_example.dart'; import 'package:example/sample/components/switch/radio_example.dart'; import 'package:example/sample/components/tabbar/brn_tab_example.dart'; @@ -423,6 +424,17 @@ class CardDataConfig { }, )); })); + children.add(GroupInfo( + groupName: "SwitchButton 普通按钮", + desc: "Switch 按钮", + isSupportTheme: true, + navigatorPage: (BuildContext context) { + Navigator.push(context, MaterialPageRoute( + builder: (BuildContext context) { + return BrnSwitchButtonExample(); + }, + )); + })); return GroupInfo(groupName: "按钮", children: children, isExpand: false); } diff --git a/example/lib/sample/home/expandable_container_widget.dart b/example/lib/sample/home/expandable_container_widget.dart index d181f177..61c3dfb1 100644 --- a/example/lib/sample/home/expandable_container_widget.dart +++ b/example/lib/sample/home/expandable_container_widget.dart @@ -5,7 +5,6 @@ import 'package:flutter/material.dart'; -import 'package:flutter/widgets.dart'; /// A single-line [ListTile] with a trailing button that expands or collapses /// the tile to reveal or hide the [children]. diff --git a/example/lib/sample/home/group_card.dart b/example/lib/sample/home/group_card.dart index 0296a77d..e63a2def 100644 --- a/example/lib/sample/home/group_card.dart +++ b/example/lib/sample/home/group_card.dart @@ -21,7 +21,7 @@ class GroupCard extends StatefulWidget { } class GroupCardState extends State - with SingleTickerProviderStateMixin { + with SingleTickerProviderStateMixin, AutomaticKeepAliveClientMixin { static final Animatable _easeInTween = CurveTween(curve: Curves.easeIn); static final Animatable _halfTween = @@ -32,6 +32,9 @@ class GroupCardState extends State late bool _initExpand; AnimationController? _animationController; + @override + bool get wantKeepAlive => true; + @override void initState() { super.initState(); @@ -101,7 +104,7 @@ class GroupCardState extends State Widget _getContentWidget() { if (widget.groupInfo == null || widget.groupInfo!.children == null) { - return SizedBox.shrink(); + return const SizedBox.shrink(); } return ListView.builder( physics: new NeverScrollableScrollPhysics(), diff --git a/example/lib/sample/home/list_item.dart b/example/lib/sample/home/list_item.dart index e37c9332..0d5cdedb 100644 --- a/example/lib/sample/home/list_item.dart +++ b/example/lib/sample/home/list_item.dart @@ -42,7 +42,10 @@ class ListItem extends StatefulWidget { _ListItemState createState() => _ListItemState(); } -class _ListItemState extends State { +class _ListItemState extends State with AutomaticKeepAliveClientMixin { + @override + bool get wantKeepAlive => true; + @override Widget build(BuildContext context) { return TextButton( diff --git a/example/lib/sample/theme/config_test_utils.dart b/example/lib/sample/theme/config_test_utils.dart index cffa9237..d0aab072 100644 --- a/example/lib/sample/theme/config_test_utils.dart +++ b/example/lib/sample/theme/config_test_utils.dart @@ -1,7 +1,4 @@ - -import 'dart:ui'; - import 'package:bruno/bruno.dart'; import 'package:flutter/material.dart'; diff --git a/example/web/main.dart b/example/web/main.dart index 002f07d0..6de19551 100644 --- a/example/web/main.dart +++ b/example/web/main.dart @@ -1,7 +1,21 @@ // TODO: change `my_app` to refer to your app package name. -import 'package:example/main.dart' as app; +import 'package:example/sample/home/home.dart'; +import 'package:flutter/material.dart'; -main() async { - app.main(); +main() { + runApp(MyApp()); +} + +class MyApp extends StatelessWidget { + @override + Widget build(BuildContext context) { + return MaterialApp( + title: 'Flutter Example', + theme: ThemeData( + primarySwatch: Colors.blue, + ), + home: HomePage(), + ); + } } \ No newline at end of file diff --git a/lib/bruno.dart b/lib/bruno.dart index 8ca380d3..54b9dab8 100644 --- a/lib/bruno.dart +++ b/lib/bruno.dart @@ -125,6 +125,8 @@ export 'src/components/form/items/group/brn_normal_group.dart'; export 'src/components/form/items/group/brn_expandable_group.dart'; export 'src/components/form/items/group/brn_portrait_radio_group.dart'; export 'src/components/form/items/group/brn_expandable_group_with_opreate.dart'; +export 'src/components/form/items/misc/brn_general_item.dart'; +export 'src/components/form/items/general/brn_switch_item.dart'; // 新增表单项 export 'src/components/form/items/title/brn_base_title_item.dart'; @@ -241,3 +243,6 @@ export 'src/components/scroll_anchor/brn_scroll_anchor_tab.dart'; // 城市选择 export 'src/components/selectcity/brn_single_select_city_page.dart'; + +// 切换 +export 'src/components/switch/brn_switch_button.dart'; diff --git a/lib/src/components/actionsheet/brn_common_action_sheet.dart b/lib/src/components/actionsheet/brn_common_action_sheet.dart index d0e297f8..e0158a45 100644 --- a/lib/src/components/actionsheet/brn_common_action_sheet.dart +++ b/lib/src/components/actionsheet/brn_common_action_sheet.dart @@ -4,9 +4,9 @@ import 'package:bruno/src/theme/brn_theme_configurator.dart'; import 'package:bruno/src/theme/configs/brn_action_sheet_config.dart'; import 'package:flutter/material.dart'; -typedef void BrnCommonActionSheetItemClickCallBack( +typedef BrnCommonActionSheetItemClickCallBack = void Function( int index, BrnCommonActionSheetItem actionItem); -typedef bool BrnCommonActionSheetItemClickInterceptor( +typedef BrnCommonActionSheetItemClickInterceptor = bool Function( int index, BrnCommonActionSheetItem actionItem); /// 每行样式 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 e50906ff..6fe2a758 100644 --- a/lib/src/components/actionsheet/brn_selected_list_action_sheet.dart +++ b/lib/src/components/actionsheet/brn_selected_list_action_sheet.dart @@ -6,6 +6,11 @@ import 'package:bruno/src/constants/brn_asset_constants.dart'; import 'package:bruno/src/utils/brn_tools.dart'; import 'package:flutter/material.dart'; +typedef BrnItemTitleBuilder = dynamic Function(int index, T entity); +typedef BrnItemDeleteCallback = bool Function(int deleteIdx, T deleteEntity); +typedef BrnListDismissCallback = void Function(bool isClosedByClearButton); + + /// 监听数据刷新和列表关闭操作 class BrnSelectedListActionSheetController extends ChangeNotifier { /// 是否刷新数据 @@ -50,7 +55,7 @@ class BrnSelectedListActionSheet { final List items; /// 获取对应 index 行内容的回调。类型必须为 String 或者自定义的 widget.自定义 widget 时,左边的 icon 会自动隐藏,自定义widget填充整行。 - final dynamic Function(int index, T entity) itemTitleBuilder; + final BrnItemTitleBuilder itemTitleBuilder; /// 控制视图隐藏/刷新列表等方法 final BrnSelectedListActionSheetController? controller; @@ -95,13 +100,13 @@ class BrnSelectedListActionSheet { final VoidCallback? onClearCanceled; /// 每一行删除按钮的点击回调。返回值:是否要删除该 entity,如果该 handler 没有实现或者返回 true,则删除 - final bool Function(int deleteIdx, T deleteEntity)? onItemDelete; + final BrnItemDeleteCallback? onItemDelete; /// 视图显示时的回调 final VoidCallback? onListShowed; /// 视图隐藏时的回调,会把是否是清空按钮触发的销毁视图回传 - final void Function(bool isClosedByClearButton)? onListDismissed; + final BrnListDismissCallback? onListDismissed; OverlayEntry? _overlayEntry; double? _leftOffset; @@ -160,10 +165,10 @@ class BrnSelectedListActionSheet { if (_overlayEntry != null) { return; } - BrnSelectedListActionSheetController? tempCcontroller = controller; - if (tempCcontroller == null) { - tempCcontroller = BrnSelectedListActionSheetController(); - tempCcontroller._isHidden = false; + BrnSelectedListActionSheetController? tempController = controller; + if (tempController == null) { + tempController = BrnSelectedListActionSheetController(); + tempController._isHidden = false; } _BrnActionSheetSelectedItemListContentWidget content = _BrnActionSheetSelectedItemListContentWidget( @@ -173,7 +178,7 @@ class BrnSelectedListActionSheet { }, itemTitleBuilder: this.itemTitleBuilder, onItemDelete: this.onItemDelete, - controller: tempCcontroller, + controller: tempController, ); content._overlayState = Overlay.of(context); OverlayEntry overlayEntry = OverlayEntry(builder: (context) { @@ -209,8 +214,8 @@ class BrnSelectedListActionSheet { 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 BrnItemTitleBuilder itemTitleBuilder; + final BrnItemDeleteCallback? onItemDelete; final BrnSelectedListActionSheetController? controller; OverlayState? _overlayState; @@ -360,7 +365,7 @@ class _BrnActionSheetSelectedItemListState Widget build(BuildContext context) { // 顶部标题处理 String title = - (widget.itemWidget.title != null && widget.itemWidget.title!.length > 0) + (widget.itemWidget.title != null && widget.itemWidget.title!.isNotEmpty) ? widget.itemWidget.title! : '已选列表'; TextStyle titleStyle = const TextStyle( diff --git a/lib/src/components/actionsheet/brn_share_action_sheet.dart b/lib/src/components/actionsheet/brn_share_action_sheet.dart index 6cfc6e62..d681a7f4 100644 --- a/lib/src/components/actionsheet/brn_share_action_sheet.dart +++ b/lib/src/components/actionsheet/brn_share_action_sheet.dart @@ -5,12 +5,12 @@ import 'package:bruno/src/utils/brn_tools.dart'; import 'package:flutter/material.dart'; /// section为所在行数(0或1),index是在第几位(从0开始记), shareItem为渠道相关信息 -typedef void BrnShareActionSheetItemClickCallBack( +typedef BrnShareActionSheetItemClickCallBack = void Function( int section, int index, BrnShareItem shareItem); /// 点击事件拦截回调(如果配置了此项,返回值为是否拦截,如果为true,则进行拦截,不进行默认回调) /// section为所在行数(0或1),index是在第几位(从0开始记),shareItem为渠道相关信息 -typedef bool BrnShareActionSheetOnItemClickInterceptor( +typedef BrnShareActionSheetOnItemClickInterceptor = bool Function( int section, int index, BrnShareItem shareItem); /// 分享元素 @@ -222,7 +222,7 @@ class BrnShareActionSheet extends StatelessWidget { )); // 添加“预设分享”容器 - if (firstSectionItems.length > 0) { + if (firstSectionItems.isNotEmpty) { tiles.add(Container( padding: EdgeInsets.only(left: leftGap, top: topGap, bottom: bottomGap), alignment: Alignment.centerLeft, @@ -243,7 +243,7 @@ class BrnShareActionSheet extends StatelessWidget { )); // 添加“自定义分享”容器 - if (secondSectionItems.length > 0) { + if (secondSectionItems.isNotEmpty) { tiles.add(Container( alignment: Alignment.centerLeft, padding: EdgeInsets.only(left: leftGap, top: topGap, bottom: bottomGap), diff --git a/lib/src/components/appraise/brn_appraise_emoji_list_view.dart b/lib/src/components/appraise/brn_appraise_emoji_list_view.dart index 93ef8d1d..80cd04e1 100644 --- a/lib/src/components/appraise/brn_appraise_emoji_list_view.dart +++ b/lib/src/components/appraise/brn_appraise_emoji_list_view.dart @@ -24,7 +24,7 @@ class BrnAppraiseEmojiListView extends StatefulWidget { this.indexes = const [0, 1, 2, 3, 4], this.titles = _defaultTitles, this.onTap}) - : assert(indexes.length > 0), + : assert(indexes.isNotEmpty), assert(titles.length == 5), super(key: key); diff --git a/lib/src/components/appraise/brn_appraise_header.dart b/lib/src/components/appraise/brn_appraise_header.dart index 6ba5a3b8..43d985cf 100644 --- a/lib/src/components/appraise/brn_appraise_header.dart +++ b/lib/src/components/appraise/brn_appraise_header.dart @@ -45,7 +45,7 @@ class BrnAppraiseHeader extends StatelessWidget { return _centerHeader(); } } - return SizedBox.shrink(); + return const SizedBox.shrink(); } Widget _centerHeader() { diff --git a/lib/src/components/button/collection/brn_bottom_button_panel.dart b/lib/src/components/button/collection/brn_bottom_button_panel.dart index 403835ec..5ee6c6f7 100644 --- a/lib/src/components/button/collection/brn_bottom_button_panel.dart +++ b/lib/src/components/button/collection/brn_bottom_button_panel.dart @@ -109,7 +109,7 @@ class BrnBottomButtonPanel extends StatelessWidget { bool enableMainButton = true, List? iconButtonList}) { if ((buttonTitleList.isEmpty) && iconButtonList == null) { - return SizedBox.shrink(); + return const SizedBox.shrink(); } if (buttonTitleList.length >= 2) { return BrnBottomButtonPanel( @@ -142,7 +142,7 @@ class BrnBottomButtonPanel extends StatelessWidget { iconButtonList: iconButtonList, ); } - return SizedBox.shrink(); + return const SizedBox.shrink(); } @override diff --git a/lib/src/components/button/collection/brn_multiple_bottom_button.dart b/lib/src/components/button/collection/brn_multiple_bottom_button.dart index 393f8eee..5cb5dcbc 100644 --- a/lib/src/components/button/collection/brn_multiple_bottom_button.dart +++ b/lib/src/components/button/collection/brn_multiple_bottom_button.dart @@ -118,8 +118,9 @@ class _BrnMultipleBottomButtonState extends State { onValueChangedAtIndex: (index, value) { //同步到外界的当前的全选状态 _controller.setState(selectAllState: value); - if (widget.onSelectAll != null) + if (widget.onSelectAll != null) { widget.onSelectAll!(value); + } }, key: Key(DateTime.now().toString()), ); diff --git a/lib/src/components/button/collection/brn_text_button_panel.dart b/lib/src/components/button/collection/brn_text_button_panel.dart index 74b3d6a6..63e20acb 100644 --- a/lib/src/components/button/collection/brn_text_button_panel.dart +++ b/lib/src/components/button/collection/brn_text_button_panel.dart @@ -46,7 +46,7 @@ class _BrnTextButtonPanelState extends State { @override Widget build(BuildContext context) { - if (widget.nameList.length > 0) { + if (widget.nameList.isNotEmpty) { Row row = Row( mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.spaceAround, @@ -74,17 +74,17 @@ class _BrnTextButtonPanelState extends State { List showWidget = []; for (int i = 0, n = widgetList.length; i < n; ++i) { showWidget.add(Expanded( - child: Center( - child: widgetList[i], - ), + child: widgetList[i], )); if (i != n - 1) { - showWidget.add(Container( - alignment: Alignment.center, - height: 26, - width: 1, - color: Color(0xFFf8f8f8), - )); + showWidget.add( + Container( + alignment: Alignment.center, + height: 26, + width: 1, + color: Color(0xFFf8f8f8), + ), + ); } } return showWidget; @@ -103,7 +103,9 @@ class _BrnTextButtonPanelState extends State { ); return GestureDetector( + behavior: HitTestBehavior.opaque, child: Container( + alignment: Alignment.center, padding: EdgeInsets.fromLTRB(4, 0, 4, 0), child: tx, ), @@ -140,6 +142,7 @@ class _BrnTextButtonPanelState extends State { : BrunoTools.getAssetImage(BrnAsset.iconDownArrow); return GestureDetector( + behavior:HitTestBehavior.opaque, child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ @@ -171,7 +174,7 @@ class _BrnTextButtonPanelState extends State { }); }); } else { - return SizedBox.shrink(); + return const SizedBox.shrink(); } } } diff --git a/lib/src/components/calendar/brn_calendar_view.dart b/lib/src/components/calendar/brn_calendar_view.dart index 119bdb62..57a029b9 100644 --- a/lib/src/components/calendar/brn_calendar_view.dart +++ b/lib/src/components/calendar/brn_calendar_view.dart @@ -267,7 +267,7 @@ class _CustomCalendarViewState extends State { ), ); } - return SizedBox.shrink(); + return const SizedBox.shrink(); } bool _isIconEnable(bool isPre) { diff --git a/lib/src/components/card/content_card/brn_enhance_number_card.dart b/lib/src/components/card/content_card/brn_enhance_number_card.dart index 155db31f..86bcf5e4 100644 --- a/lib/src/components/card/content_card/brn_enhance_number_card.dart +++ b/lib/src/components/card/content_card/brn_enhance_number_card.dart @@ -5,7 +5,6 @@ import 'package:bruno/src/constants/brn_strings_constants.dart'; import 'package:bruno/src/theme/brn_theme.dart'; import 'package:bruno/src/utils/brn_tools.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/widgets.dart'; /// 强化数字展示的组件 /// @@ -102,7 +101,7 @@ class BrnEnhanceNumberCard extends StatelessWidget { .enhanceNumberCardConfig .merge(defaultConfig); - if (itemChildren == null || itemChildren!.length == 0) { + if (itemChildren == null || itemChildren!.isEmpty) { return Container( height: 0, width: 0, diff --git a/lib/src/components/card/content_card/brn_pair_info_rich_grid.dart b/lib/src/components/card/content_card/brn_pair_info_rich_grid.dart index 4a7ccb51..3e74a527 100644 --- a/lib/src/components/card/content_card/brn_pair_info_rich_grid.dart +++ b/lib/src/components/card/content_card/brn_pair_info_rich_grid.dart @@ -215,12 +215,12 @@ class BrnRichGridInfo { BrnPairRichInfoGridConfig? themeData, }) { themeData ??= BrnPairRichInfoGridConfig(); - themeData = themeData.merge(BrnPairRichInfoGridConfig( - linkTextStyle: BrnTextStyle(color: clickColor))); themeData = BrnThemeConfigurator.instance .getConfig(configId: themeData.configId) .pairRichInfoGridConfig .merge(themeData); + themeData = themeData.merge(BrnPairRichInfoGridConfig( + linkTextStyle: BrnTextStyle(color: clickColor))); Widget _getQuestionImage(bool isKey) { return GestureDetector( diff --git a/lib/src/components/card/content_card/brn_pair_info_table.dart b/lib/src/components/card/content_card/brn_pair_info_table.dart index c1e10fdd..564ca01e 100644 --- a/lib/src/components/card/content_card/brn_pair_info_table.dart +++ b/lib/src/components/card/content_card/brn_pair_info_table.dart @@ -103,6 +103,9 @@ class BrnPairInfoTable extends StatefulWidget { ///可以参考[_MaxWrapTableWidth]实现自定义的展示规则,指定长度等 final TableColumnWidth? customKeyWidth; + /// Table 展开收起状态变化的回调 + final ValueChanged? onFolded; + BrnPairInfoTable({ Key? key, required this.children, @@ -112,8 +115,9 @@ class BrnPairInfoTable extends StatefulWidget { this.rowDistance, this.itemSpacing, this.isFolded = true, - this.themeData, + this.onFolded, this.customKeyWidth, + this.themeData }); @override @@ -140,7 +144,7 @@ class _BrnPairInfoTableState extends State { BrnInfoModal? indexModal; // 是否具备展开收起功能 如果不展示则显示全部 - bool canExpanded = false; + bool _canFold = false; late BrnPairInfoTableConfig themeData; @@ -161,12 +165,12 @@ class _BrnPairInfoTableState extends State { widget.expandAtIndex >= (widget.children.length - 1)) { _expandAtIndex = -1; showList = widget.children; - canExpanded = false; + _canFold = false; } else { indexModal = widget.children[_expandAtIndex]; foldList = _generateFoldList(); expandedList = _generateExpandedList(); - canExpanded = true; + _canFold = true; } super.initState(); } @@ -186,7 +190,7 @@ class _BrnPairInfoTableState extends State { Widget build(BuildContext context) { Widget showWidget; - if (canExpanded) { + if (_canFold) { if (_isFolded) { showList = foldList; } else { @@ -296,6 +300,7 @@ class _BrnPairInfoTableState extends State { GestureDetector gdt = GestureDetector( child: row, onTap: () { + widget.onFolded?.call(!_isFolded); setState(() { _isFolded = !_isFolded; }); @@ -317,7 +322,7 @@ class _BrnPairInfoTableState extends State { Widget foldButtonWidget = layerCtn; /// 将原有的value显示替换为 stack - BrnInfoModal brnMetaInfoModal = BrnInfoModal( + BrnInfoModal brnInfoModal = BrnInfoModal( isArrow: indexModal!.isArrow, keyPart: indexModal!.keyPart, valuePart: indexModal!.valuePart, @@ -325,13 +330,13 @@ class _BrnPairInfoTableState extends State { Container stack = Container( child: Stack( children: [ - _finalValueWidget(brnMetaInfoModal, itemSpacing: 0), + _finalValueWidget(brnInfoModal, itemSpacing: 0), Positioned(bottom: 0, right: 0, child: foldButtonWidget), ], ), ); - brnMetaInfoModal.valuePart = stack; - return brnMetaInfoModal; + brnInfoModal.valuePart = stack; + return brnInfoModal; } BrnInfoModal _expandedButtonWidget() { @@ -355,6 +360,7 @@ class _BrnPairInfoTableState extends State { GestureDetector gdt = GestureDetector( child: row, onTap: () { + widget.onFolded?.call(!_isFolded); setState(() { _isFolded = !_isFolded; }); @@ -375,7 +381,7 @@ class _BrnPairInfoTableState extends State { ///收起的widget Widget foldButtonWidget = layerCtn; - BrnInfoModal brnMetaInfoModal = BrnInfoModal( + BrnInfoModal brnInfoModal = BrnInfoModal( isArrow: widget.children.last.isArrow, keyPart: widget.children.last.keyPart, valuePart: widget.children.last.valuePart, @@ -384,13 +390,13 @@ class _BrnPairInfoTableState extends State { Container stack = Container( child: Stack( children: [ - _finalValueWidget(brnMetaInfoModal, itemSpacing: 0), + _finalValueWidget(brnInfoModal, itemSpacing: 0), Positioned(bottom: 0, right: 0, child: foldButtonWidget), ], ), ); - brnMetaInfoModal.valuePart = stack; - return brnMetaInfoModal; + brnInfoModal.valuePart = stack; + return brnInfoModal; } Widget _valueTitleText(String text, @@ -578,9 +584,7 @@ class BrnFollowPairInfo extends StatelessWidget with PairInfoPart { if (infoModal.valueClickCallback != null) { value = GestureDetector( onTap: () { - if (infoModal.valueClickCallback != null) { - infoModal.valueClickCallback!(); - } + infoModal.valueClickCallback?.call(); }, child: value, ); @@ -702,7 +706,7 @@ class BrnAlignPairInfo extends StatelessWidget with PairInfoPart { /// 用于展示信息的modal,封装了key和value的基本信息 /// /// 基本的文本展示只需 传入keyPart和valuePart为字符串 -/// 复杂的展示 需要传入Widget,BrnMetaInfoModal的若干静态方法 提供了丰富简便的富文本使用方式 +/// 复杂的展示 需要传入Widget,BrnInfoModal的若干静态方法 提供了丰富简便的富文本使用方式 /// class BrnInfoModal { /// 方便业务调用,具备两种类型 string 和 widget @@ -749,6 +753,10 @@ class BrnInfoModal { BrnPairInfoTableConfig? themeData, }) { themeData ??= BrnPairInfoTableConfig(); + themeData = BrnThemeConfigurator.instance + .getConfig(configId: themeData.configId) + .pairInfoTableConfig + .merge(themeData); themeData = themeData.merge(BrnPairInfoTableConfig( itemSpacing: itemSpacing, keyTextStyle: BrnTextStyle(fontSize: fontSize), @@ -756,10 +764,6 @@ class BrnInfoModal { .merge(BrnTextStyle.withStyle(valueTextStyle)), linkTextStyle: BrnTextStyle(fontSize: fontSize, color: linkColor) .merge(BrnTextStyle.withStyle(valueTextStyle)))); - themeData = BrnThemeConfigurator.instance - .getConfig(configId: themeData.configId) - .pairInfoTableConfig - .merge(themeData); Widget valueWidget; if (isArrow) { @@ -845,16 +849,16 @@ class BrnInfoModal { BrnPairInfoTableConfig? themeData, }) { themeData ??= BrnPairInfoTableConfig(); + themeData = BrnThemeConfigurator.instance + .getConfig(configId: themeData.configId) + .pairInfoTableConfig + .merge(themeData); themeData = themeData.merge(BrnPairInfoTableConfig( itemSpacing: itemSpacing, keyTextStyle: BrnTextStyle(fontSize: fontSize) .merge(BrnTextStyle.withStyle(keyTextStyle)), valueTextStyle: BrnTextStyle(fontSize: fontSize) .merge(BrnTextStyle.withStyle(valueTextStyle)))); - themeData = BrnThemeConfigurator.instance - .getConfig(configId: themeData.configId) - .pairInfoTableConfig - .merge(themeData); dynamic valueWidget; dynamic keyWidget; @@ -986,16 +990,16 @@ class BrnInfoModal { BrnPairInfoTableConfig? themeData, }) { themeData ??= BrnPairInfoTableConfig(); + themeData = BrnThemeConfigurator.instance + .getConfig(configId: themeData.configId) + .pairInfoTableConfig + .merge(themeData); themeData = themeData.merge(BrnPairInfoTableConfig( itemSpacing: itemSpacing, keyTextStyle: BrnTextStyle(fontSize: fontSize) .merge(BrnTextStyle.withStyle(keyTextStyle)), valueTextStyle: BrnTextStyle(fontSize: fontSize) .merge(BrnTextStyle.withStyle(valueTextStyle)))); - themeData = BrnThemeConfigurator.instance - .getConfig(configId: themeData.configId) - .pairInfoTableConfig - .merge(themeData); BrnRichTextGenerator keyGen = BrnRichTextGenerator(); if (headIcon != null) { @@ -1036,15 +1040,15 @@ class BrnInfoModal { BrnPairInfoTableConfig? themeData, }) { themeData ??= BrnPairInfoTableConfig(); + themeData = BrnThemeConfigurator.instance + .getConfig(configId: themeData.configId) + .pairInfoTableConfig + .merge(themeData); themeData = themeData.merge(BrnPairInfoTableConfig( itemSpacing: itemSpacing, keyTextStyle: BrnTextStyle(fontSize: fontSize), valueTextStyle: BrnTextStyle(fontSize: fontSize) .merge(BrnTextStyle.withStyle(valueTextStyle)))); - themeData = BrnThemeConfigurator.instance - .getConfig(configId: themeData.configId) - .pairInfoTableConfig - .merge(themeData); return BrnInfoModal( keyPart: keyTitle, diff --git a/lib/src/components/card_title/brn_action_card_title.dart b/lib/src/components/card_title/brn_action_card_title.dart index 4cb00a2c..4cadc255 100644 --- a/lib/src/components/card_title/brn_action_card_title.dart +++ b/lib/src/components/card_title/brn_action_card_title.dart @@ -134,7 +134,7 @@ class BrnActionCardTitle extends StatelessWidget { ); } - return SizedBox.shrink(); + return const SizedBox.shrink(); } Widget _arrowWidget() { diff --git a/lib/src/components/card_title/brn_common_card_title.dart b/lib/src/components/card_title/brn_common_card_title.dart index cea76fdf..2bcb46a0 100644 --- a/lib/src/components/card_title/brn_common_card_title.dart +++ b/lib/src/components/card_title/brn_common_card_title.dart @@ -73,6 +73,13 @@ class BrnCommonCardTitle extends StatelessWidget { /// 内容的padding 默认上下16 左右0 final EdgeInsetsGeometry? padding; + /// 标题最大行数 + final int? titleMaxLines; + + /// 标题 Overflow 展示方式,默认 TextOverflow.clip + /// 注意,由于 subTitleWidget 与 title 是流式布局,所以 subTitleWidget 会折叠 + final TextOverflow titleOverflow; + final BrnCardTitleConfig? themeData; BrnCommonCardTitle( @@ -86,7 +93,9 @@ class BrnCommonCardTitle extends StatelessWidget { this.detailColor, this.alignment, this.padding, - this.themeData}) + this.titleMaxLines, + this.titleOverflow = TextOverflow.clip, + this.themeData}) : super(key: key); @override @@ -174,6 +183,8 @@ class BrnCommonCardTitle extends StatelessWidget { } var titleWidget = RichText( textScaleFactor: MediaQuery.of(context).textScaleFactor, + maxLines: this.titleMaxLines, + overflow: this.titleOverflow, text: TextSpan( text: title, style: defaultConfig.titleWithHeightTextStyle.generateTextStyle(), diff --git a/lib/src/components/charts/brn_doughunt_chart/brn_doughnut_chart.dart b/lib/src/components/charts/brn_doughunt_chart/brn_doughnut_chart.dart index 30ea9fb9..ce8a10ce 100644 --- a/lib/src/components/charts/brn_doughunt_chart/brn_doughnut_chart.dart +++ b/lib/src/components/charts/brn_doughunt_chart/brn_doughnut_chart.dart @@ -234,9 +234,10 @@ class BrnDoughnut extends CustomPainter { double radain = pointRadianInSector(position); if (item.startRadius < radain && radain < (item.startRadius + item.radius)) { - if (null != brnDoughnutSelectCallback) + if (null != brnDoughnutSelectCallback) { brnDoughnutSelectCallback!( item.startRadius == selectedItem?.startRadius ? null : item); + } break; } } diff --git a/lib/src/components/charts/brn_progress_bar_chart/brn_progress_bar_chart.dart b/lib/src/components/charts/brn_progress_bar_chart/brn_progress_bar_chart.dart index fb12f8de..16d142d3 100644 --- a/lib/src/components/charts/brn_progress_bar_chart/brn_progress_bar_chart.dart +++ b/lib/src/components/charts/brn_progress_bar_chart/brn_progress_bar_chart.dart @@ -199,8 +199,9 @@ class BrnProgressBarChartState extends State { widget.selectedHintTextBackgroundColor, brnProgressBarChartSelectCallback: (BrnProgressBarItem? item) { - if (null != widget.barChartSelectCallback) + if (null != widget.barChartSelectCallback) { widget.barChartSelectCallback!(item); + } setState(() { _selectedBarItem = item; }); @@ -212,19 +213,60 @@ class BrnProgressBarChartState extends State { ), ); } else if (BarChartStyle.horizontal == widget.barChartStyle) { + double yAxisWidth = + BrnProgressBarChartPainter.maxYAxisWidth(widget.yAxis); return Padding( padding: widget.padding, - child: CustomPaint( - size: chartSize, - painter: BrnProgressBarChartPainter( - xAxis: widget.xAxis, - yAxis: widget.yAxis, - barChartStyle: widget.barChartStyle, - singleBarWidth: widget.singleBarWidth, - barMaxValue: widget.barMaxValue, - barGroupSpace: widget.barGroupSpace, - barBundleList: widget.barBundleList, - ), + child: Stack( + children: [ + Padding( + padding: EdgeInsets.only(left: yAxisWidth), + child: CustomPaint( + size: chartSize, + painter: BrnProgressBarChartPainter( + drawBar: false, + drawY: false, + xAxis: widget.xAxis, + yAxis: widget.yAxis, + barChartStyle: widget.barChartStyle, + singleBarWidth: widget.singleBarWidth, + barMaxValue: widget.barMaxValue, + barGroupSpace: widget.barGroupSpace, + barBundleList: widget.barBundleList, + ), + ), + ), + Padding( + padding: EdgeInsets.only(bottom: 22), + child: SingleChildScrollView( + scrollDirection: Axis.vertical, + child: CustomPaint( + size: chartSize, + painter: BrnProgressBarChartPainter( + drawX: false, + xAxis: widget.xAxis, + yAxis: widget.yAxis, + barChartStyle: widget.barChartStyle, + singleBarWidth: widget.singleBarWidth, + barMaxValue: widget.barMaxValue, + barGroupSpace: widget.barGroupSpace, + barBundleList: widget.barBundleList, + onBarItemClickInterceptor: + widget.onBarItemClickInterceptor, + selectedBarItem: _selectedBarItem, + selectedHintTextColor: widget.selectedHintTextColor, + selectedHintTextBackgroundColor: + widget.selectedHintTextBackgroundColor, + brnProgressBarChartSelectCallback: (BrnProgressBarItem? item) { + widget.barChartSelectCallback?.call(item); + setState(() { + _selectedBarItem = item; + }); + }), + ), + ), + ), + ], ), ); } else { diff --git a/lib/src/components/charts/brn_progress_bar_chart/brn_progress_bar_chart_painter.dart b/lib/src/components/charts/brn_progress_bar_chart/brn_progress_bar_chart_painter.dart index e5d0e673..1e24733b 100644 --- a/lib/src/components/charts/brn_progress_bar_chart/brn_progress_bar_chart_painter.dart +++ b/lib/src/components/charts/brn_progress_bar_chart/brn_progress_bar_chart_painter.dart @@ -13,7 +13,7 @@ typedef BrnProgressBarChartSelectCallback = void Function( BrnProgressBarItem? barItem); /// 点击柱状数据的拦截器 -typedef bool OnBarItemClickInterceptor( +typedef OnBarItemClickInterceptor = bool Function( int barBundleIndex, BrnProgressBarBundle barBundle, int barGroupIndex, @@ -69,12 +69,17 @@ class ChartAxis { /// 0/刻度偏移量 double leadingSpace = 30; + TextStyle textStyle = TextStyle(color: Color(0x999999), fontSize: 12); + /// 倾斜坐标轴文本,避免文本距离过近,目前仅针对X轴文本有效 + final bool inclineText; + ChartAxis({ required this.axisItemList, this.hasMark = true, this.axisStyle = AxisStyle.axisStyleSolid, + this.inclineText = false, }); } @@ -231,27 +236,29 @@ class BrnProgressBarChartPainter extends CustomPainter { return Size(textWidth, textHeight); } - if (yAxis.axisItemList.length > 0) { + if (yAxis.axisItemList.isNotEmpty) { //确定y轴文本最大宽度,以及每个文本大小 yAxis.axisItemList.forEach((AxisItem item) { Size textSize = getTextAreaSize(item.showText, yAxis.textStyle); item.textSize = textSize; - if (textSize.width > yAxis.maxTextWidth) + if (textSize.width > yAxis.maxTextWidth) { yAxis.maxTextWidth = textSize.width; + } }); } return yAxis.maxTextWidth + 10; } void _prepareData(Canvas canvas, Size size) { - if (this.yAxis.axisItemList.length > 0) { + if (this.yAxis.axisItemList.isNotEmpty) { //确定y轴文本最大宽度,以及每个文本大小 this.yAxis.axisItemList.forEach((AxisItem item) { Size textSize = this.getTextAreaSize(item.showText, this.yAxis.textStyle); item.textSize = textSize; - if (textSize.width > this.yAxis.maxTextWidth) + if (textSize.width > this.yAxis.maxTextWidth) { this.yAxis.maxTextWidth = textSize.width; + } }); this.yAxisRect = Rect.fromLTWH( @@ -259,21 +266,32 @@ class BrnProgressBarChartPainter extends CustomPainter { 0, this.yAxis.maxTextWidth + _yTextAxisSpace, size.height - - (0 == this.xAxis.axisItemList.length ? 0 : this._xAxisHeight)); + (this.xAxis.axisItemList.isEmpty ? 0 : this._xAxisHeight)); } - if (!this.drawY) + if (!this.drawY) { this.yAxisRect = Rect.fromLTWH( 0, 0, 0, size.height - - (0 == this.xAxis.axisItemList.length ? 0 : this._xAxisHeight)); + (this.xAxis.axisItemList.isEmpty ? 0 : this._xAxisHeight)); + } this.xAxisRect = Rect.fromPoints( this.yAxisRect.bottomRight, Offset(size.width, size.height)); - if (this.barBundleList.length > 0) { + if (this.barChartStyle == BarChartStyle.horizontal) { + if (!this.drawX) { + // 仅画x + this.xAxisRect = Rect.fromLTWH(this.yAxisRect.bottomRight.dx, + size.height, size.width - this.yAxisRect.width, 0); + this.yAxisRect = Rect.fromLTWH( + 0, 0, this.yAxis.maxTextWidth + _yTextAxisSpace, size.height - (this.xAxis.axisItemList.isEmpty ? 0 : this._xAxisHeight)); + } + } + + if (this.barBundleList.isNotEmpty) { this.contentRect = Rect.fromPoints(this.yAxisRect.topRight, this.xAxisRect.topRight); } @@ -377,7 +395,7 @@ class BrnProgressBarChartPainter extends CustomPainter { } void _drawXAxisIn(Canvas canvas, Rect xAxisRect) { - if (0 == this.xAxis.axisItemList.length) return; + if (this.xAxis.axisItemList.isEmpty) return; if (AxisStyle.axisStyleSolid == this.xAxis.axisStyle) { Offset xLineStart = xAxisRect.topLeft; Offset xLineEnd = xAxisRect.topRight; @@ -421,8 +439,16 @@ class BrnProgressBarChartPainter extends CustomPainter { double textWidth = textPainter.size.width; - textPainter.paint(canvas, - Offset(currentOffset.dx - textWidth / 2, currentOffset.dy + 5)); + if (this.xAxis.inclineText == true) { + canvas.save(); + canvas.translate(currentOffset.dx, currentOffset.dy + 3); + canvas.rotate(-0.3); + textPainter.paint(canvas, Offset(-textWidth, 0)); + canvas.restore(); + } else { + textPainter.paint(canvas, + Offset(currentOffset.dx - textWidth / 2, currentOffset.dy + 5)); + } } } else if (BarChartStyle.vertical == this.barChartStyle) { Paint markLinkePaint = Paint()..color = Color(0xff222222); @@ -457,7 +483,7 @@ class BrnProgressBarChartPainter extends CustomPainter { } void _drawYAxisIn(Canvas canvas, Rect yAxisRect) { - if (0 == this.yAxis.axisItemList.length) return; + if (this.yAxis.axisItemList.isEmpty) return; if (AxisStyle.axisStyleSolid == this.yAxis.axisStyle) { Offset yLineStart = yAxisRect.bottomRight; Offset yLineEnd = yAxisRect.topRight; @@ -719,21 +745,57 @@ class BrnProgressBarChartPainter extends CustomPainter { RRect barRRect = RRect.fromRectAndCorners(barItem.barRect!, topRight: Radius.circular(4), bottomRight: Radius.circular(4)); - Shader shader = LinearGradient( + if (this.selectedBarItem != null) { + // 有选中的柱形,选中柱形保持原样,未选中的置灰 + Shader shader; + if (this.selectedBarItem!.barRect == barItem.barRect) { + // 选中的柱形 + shader = LinearGradient( begin: Alignment.centerLeft, end: Alignment.centerRight, tileMode: TileMode.clamp, colors: barBundle.colors) - .createShader(barItem.barRect!); - Paint barPaint = Paint() - ..shader = shader - ..isAntiAlias = true - ..strokeCap = StrokeCap.round - ..strokeWidth = 1.5 - ..style = PaintingStyle.fill; - - canvas.drawRRect(barRRect, barPaint); + .createShader(barItem.barRect!); + } else { + // 未选中需要置灰的柱形 + shader = LinearGradient( + begin: Alignment.centerLeft, + end: Alignment.centerRight, + tileMode: TileMode.clamp, + colors: [this.unselectedColor, this.unselectedColor]) + .createShader(barItem.barRect!); + } + Paint barPaint = Paint() + ..shader = shader + ..isAntiAlias = true + ..strokeCap = StrokeCap.round + ..strokeWidth = 1.5 + ..style = PaintingStyle.fill; + canvas.drawRRect(barRRect, barPaint); + if (this.selectedBarItem!.barRect == barItem.barRect) { + // 选中柱形的虚线以及 HintText + this._drawDashLineOn( + canvas, + barItem.barRect!.centerLeft, + Offset(this.xAxisRect.right, barItem.barRect!.centerLeft.dy), + Color(0xff222222)); + } + } else { + Shader shader = LinearGradient( + begin: Alignment.centerLeft, + end: Alignment.centerRight, + tileMode: TileMode.clamp, + colors: barBundle.colors) + .createShader(barItem.barRect!); + Paint barPaint = Paint() + ..shader = shader + ..isAntiAlias = true + ..strokeCap = StrokeCap.round + ..strokeWidth = 1.5 + ..style = PaintingStyle.fill; + canvas.drawRRect(barRRect, barPaint); + } // 绘制柱状图上的数值 TextStyle textStyle = TextStyle(color: Colors.white, fontSize: 12); this.barItemEnumerator((int barBundleIndex, @@ -750,6 +812,60 @@ class BrnProgressBarChartPainter extends CustomPainter { textPainter.paint(canvas, textOffset); }); }); + + + // 最后画选中柱形的提示文字,否则可能被遮挡 + if (null != this.selectedBarItem) { + // 画选中文字 Start + TextPainter selectedBarTextPainter = TextPainter( + text: TextSpan( + text: selectedBarItem!.selectedHintText ?? + (selectedBarItem!.text ?? ''), + style: + TextStyle(fontSize: 12, color: this.selectedHintTextColor)), + textDirection: TextDirection.ltr) + ..layout(maxWidth: double.infinity, minWidth: 0); + double textWidth = selectedBarTextPainter.size.width; + double textHeight = selectedBarTextPainter.size.height; + + Offset selectedBarTextBgCenterOffset; + if (selectedBarItem!.barRect!.centerLeft.dy + 10 + textHeight + 10 * 2 > + this.contentRect.bottom) { + // 需要显示在上侧 + selectedBarTextBgCenterOffset = Offset( + this.xAxisRect.bottomRight.dx - 10 - 10 - textWidth / 2, + selectedBarItem!.barRect!.centerRight.dy - (10 + textWidth / 2)); + } else { + // 需要显示在下侧 + selectedBarTextBgCenterOffset = Offset( + this.xAxisRect.bottomRight.dx - 10 - 10 - textWidth / 2, + selectedBarItem!.barRect!.centerRight.dy + (10 + textWidth / 2)); + } + + // 文本背景区域超出整个图形范围 + if (textHeight / 2 + 8 > selectedBarTextBgCenterOffset.dy) { + selectedBarTextBgCenterOffset = + Offset(selectedBarTextBgCenterOffset.dx, textHeight / 2 + 8); + } + + // 画选中文字背景 + Paint selectTextBgPaint = Paint() + ..color = this.selectedHintTextBackgroundColor + ..style = PaintingStyle.fill; + RRect selectTextBgRRect = RRect.fromRectAndRadius( + Rect.fromCenter( + center: selectedBarTextBgCenterOffset, + width: textWidth + 10 * 2, + height: textHeight + 8 * 2), + Radius.circular(2)); + canvas.drawRRect(selectTextBgRRect, selectTextBgPaint); + selectedBarTextPainter.paint( + canvas, + Offset(selectedBarTextBgCenterOffset.dx - textWidth / 2, + selectedBarTextBgCenterOffset.dy - textHeight / 2)); + + // 画选中文字 End + } } Size getTextAreaSize(String text, TextStyle textStyle) { @@ -767,8 +883,7 @@ class BrnProgressBarChartPainter extends CustomPainter { @override bool? hitTest(Offset position) { - if (this.brnProgressBarChartSelectCallback != null && - BarChartStyle.vertical == this.barChartStyle) { + if (this.brnProgressBarChartSelectCallback != null) { this.barItemEnumerator((int barBundleIndex, BrnProgressBarBundle barBundle, int barGroupIndex, diff --git a/lib/src/components/charts/broken_line/brn_line_painter.dart b/lib/src/components/charts/broken_line/brn_line_painter.dart index 5b0f850f..cc1fc89a 100644 --- a/lib/src/components/charts/broken_line/brn_line_painter.dart +++ b/lib/src/components/charts/broken_line/brn_line_painter.dart @@ -270,7 +270,7 @@ class BrnLinePainter extends BrnBasePainter { double? x0, y0, x1, y1, t0; var path = Path(); for (int i = 0; i < targetPoints.length; i++) { - var t1; + double? t1; var x = targetPoints[i].x; var y = targetPoints[i].y; if (x == x1 && y == y1) break; @@ -512,7 +512,7 @@ class BrnLinePainter extends BrnBasePainter { var length = item.points.length; for (var i = 0; i < length; i++) { if (item.points[i].pointText == null || - item.points[i].pointText!.length == 0) { + item.points[i].pointText!.isEmpty) { continue; } var tpX = TextPainter( @@ -545,7 +545,7 @@ class BrnLinePainter extends BrnBasePainter { bool isAdjustPosition( int lineIndex, Point currentPoint, List>> lines) { List> sameXPoints = getSameXValuePoints(currentPoint, lines); - if (sameXPoints.length > 0) { + if (sameXPoints.isNotEmpty) { if (currentPoint.distanceTo(sameXPoints[0]) == 0) { return lineIndex > 0; } else if (currentPoint.distanceTo(sameXPoints[0]) < 40) { diff --git a/lib/src/components/charts/funnel_chart.dart b/lib/src/components/charts/funnel_chart.dart index a2ac4c7d..b0a4a61b 100644 --- a/lib/src/components/charts/funnel_chart.dart +++ b/lib/src/components/charts/funnel_chart.dart @@ -267,8 +267,9 @@ abstract class RenderFunnelChart extends RenderBox @override void setupParentData(RenderBox child) { - if (child.parentData is! BrnFunnelChartParentData) + if (child.parentData is! BrnFunnelChartParentData) { child.parentData = BrnFunnelChartParentData(); + } } @override diff --git a/lib/src/components/charts/radar_chart.dart b/lib/src/components/charts/radar_chart.dart index 4e7e2804..6a74b948 100644 --- a/lib/src/components/charts/radar_chart.dart +++ b/lib/src/components/charts/radar_chart.dart @@ -339,8 +339,9 @@ class RenderRadarChart extends RenderBox @override void setupParentData(RenderBox child) { - if (child.parentData is! BrnRadarChartParentData) + if (child.parentData is! BrnRadarChartParentData) { child.parentData = BrnRadarChartParentData(); + } } double _getIntrinsicDimensionHorizontal( diff --git a/lib/src/components/dialog/brn_dialog.dart b/lib/src/components/dialog/brn_dialog.dart index 09c3e106..dd0049ec 100644 --- a/lib/src/components/dialog/brn_dialog.dart +++ b/lib/src/components/dialog/brn_dialog.dart @@ -311,13 +311,14 @@ class BrnDialog extends AlertDialog { /// 内容widget:以contentWidget为准,辅以message生成的Text Widget _generateContentWidget( BuildContext context, BrnDialogConfig dialogConfig) { - if (contentWidget != null) + if (contentWidget != null) { return Flexible( child: DefaultTextStyle( style: dialogConfig.contentTextStyle.generateTextStyle(), child: contentWidget!, ), ); + } return Padding( padding: _configContentPadding(dialogConfig), @@ -334,13 +335,14 @@ class BrnDialog extends AlertDialog { /// 警示widget:以warningWidget为准,辅以warning生成的Text Widget _generateWarningWidget( BuildContext context, BrnDialogConfig dialogConfig) { - if (warningWidget != null) + if (warningWidget != null) { return Flexible( child: DefaultTextStyle( style: dialogConfig.warningTextStyle.generateTextStyle(), child: warningWidget!, ), ); + } return Padding( padding: _configWarningPadding(dialogConfig), diff --git a/lib/src/components/dialog/brn_middle_input_diaolg.dart b/lib/src/components/dialog/brn_middle_input_diaolg.dart index 6092c097..edd807f2 100644 --- a/lib/src/components/dialog/brn_middle_input_diaolg.dart +++ b/lib/src/components/dialog/brn_middle_input_diaolg.dart @@ -1,5 +1,5 @@ import 'package:bruno/src/components/dialog/brn_dialog.dart'; -import 'package:bruno/src/theme/brn_theme_configurator.dart'; +import 'package:bruno/src/theme/brn_theme.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; @@ -56,7 +56,10 @@ class BrnMiddleInputDialog { /// 点击取消/确认按钮之后,是否自动关闭弹窗,默认为 true,关闭 final bool dismissOnActionsTap; - const BrnMiddleInputDialog( + /// 点击取消/确认按钮之后,是否自动关闭弹窗,默认为 true,关闭 + BrnDialogConfig? themeData; + + BrnMiddleInputDialog( {this.title, this.message, this.hintText, @@ -73,7 +76,14 @@ class BrnMiddleInputDialog { this.onCancel, this.dismissOnActionsTap = true, this.barrierDismissible = true, - this.autoFocus = false}); + this.autoFocus = false, + this.themeData}) { + this.themeData ??= BrnDialogConfig(); + this.themeData = BrnThemeConfigurator.instance + .getConfig(configId: this.themeData!.configId) + .dialogConfig + .merge(this.themeData); + } void show(BuildContext context) { _doShow(context); @@ -82,11 +92,19 @@ class BrnMiddleInputDialog { void _doShow(BuildContext context) { String _value = inputEditingController?.text ?? ""; var dialogMessageWidgets = []; - if (message != null && message!.length > 0) { - dialogMessageWidgets.add(Text( - message!, - style: cContentTextStyle, - textAlign: cContentTextAlign, + if (message != null && message!.isNotEmpty) { + dialogMessageWidgets.add(Flexible( + child: SingleChildScrollView( + physics: BouncingScrollPhysics(), + child: Align( + alignment: _getMessageAlign(themeData!.contentTextAlign), + child: Text( + message!, + style: themeData!.contentTextStyle.generateTextStyle(), + textAlign: themeData!.contentTextAlign, + ), + ), + ), )); dialogMessageWidgets.add(Container( height: 12, @@ -158,8 +176,9 @@ class BrnMiddleInputDialog { confirm: confirmText, title: title, barrierDismissible: barrierDismissible, + themeData: themeData, messageWidget: Padding( - padding: const EdgeInsets.only(top: 12, left: 24, right: 24), + padding: themeData!.contentPaddingLg, child: Column( mainAxisSize: MainAxisSize.min, children: dialogMessageWidgets, @@ -170,4 +189,15 @@ class BrnMiddleInputDialog { if (onCancel != null) onCancel!(); }); } + + + Alignment _getMessageAlign(TextAlign messageTextAlign) { + if(messageTextAlign == TextAlign.left || messageTextAlign == TextAlign.start) { + return Alignment.centerLeft; + } + if(messageTextAlign == TextAlign.right || messageTextAlign == TextAlign.end) { + return Alignment.centerRight; + } + return Alignment.center; + } } \ No newline at end of file diff --git a/lib/src/components/dialog/brn_multi_select_dialog.dart b/lib/src/components/dialog/brn_multi_select_dialog.dart index 40e979e8..d75c5b1c 100644 --- a/lib/src/components/dialog/brn_multi_select_dialog.dart +++ b/lib/src/components/dialog/brn_multi_select_dialog.dart @@ -1,5 +1,4 @@ import 'package:bruno/src/components/dialog/brn_content_export_dialog.dart'; -import 'package:bruno/src/components/dialog/brn_dialog.dart'; import 'package:bruno/src/components/line/brn_line.dart'; import 'package:bruno/src/constants/brn_asset_constants.dart'; import 'package:bruno/src/theme/brn_theme_configurator.dart'; @@ -162,6 +161,7 @@ class MultiSelectPickerWidgetState extends State { Widget build(BuildContext context) { return BrnContentExportWidget( Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ _generateContentWidget(), Container( @@ -235,22 +235,27 @@ class MultiSelectPickerWidgetState extends State { /// 若无则以 messageText 生成widget 填充, /// 都没设置则为空 Container Widget _generateContentWidget() { - if (widget.messageWidget != null) + if (widget.messageWidget != null) { return Padding( padding: EdgeInsets.only(bottom: 8, left: 20, right: 20), child: widget.messageWidget, ); + } if (!BrunoTools.isEmpty(widget.messageText)) { return Padding( padding: EdgeInsets.only(bottom: 8, left: 20, right: 20), child: Text( widget.messageText!, - style: cContentTextStyle, + style: BrnThemeConfigurator.instance + .getConfig() + .dialogConfig + .contentTextStyle + .generateTextStyle(), ), ); } - return Container(); + return const SizedBox.shrink(); } Widget _buildItem(BuildContext context, int index) { diff --git a/lib/src/components/dialog/brn_scrollable_text_dialog.dart b/lib/src/components/dialog/brn_scrollable_text_dialog.dart index 9de95c0d..451b636b 100644 --- a/lib/src/components/dialog/brn_scrollable_text_dialog.dart +++ b/lib/src/components/dialog/brn_scrollable_text_dialog.dart @@ -112,21 +112,25 @@ class BrnScrollableText extends StatelessWidget { Widget build(BuildContext context) { return BrnContentExportWidget( Padding( - padding: EdgeInsets.fromLTRB(20, 0, 20, 0), + padding: EdgeInsets.fromLTRB(20, 0, 8, 0), child: Container( - constraints: BoxConstraints(maxHeight: 220), - child: Scrollbar( - child: SingleChildScrollView( - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ + constraints: BoxConstraints(maxHeight: 220), + child: Scrollbar( + radius: Radius.circular(2.0), + thickness: 4.0, + child: Padding( + padding: EdgeInsets.only(right: 8), + child: SingleChildScrollView( + child: Column(mainAxisSize: MainAxisSize.min, children: [ BrnCSS2Text.toTextView(contentText, linksCallback: linksCallback, defaultStyle: TextStyle( - fontSize: textFontSize, - color: textColor, - fontWeight: FontWeight.normal)) - ])))), + fontSize: textFontSize, color: textColor, fontWeight: FontWeight.normal)) + ]), + ), + ), + ), + ), ), title: title, isClose: isClose, diff --git a/lib/src/components/dialog/brn_share_dialog.dart b/lib/src/components/dialog/brn_share_dialog.dart index 8e282877..a45f761c 100644 --- a/lib/src/components/dialog/brn_share_dialog.dart +++ b/lib/src/components/dialog/brn_share_dialog.dart @@ -9,15 +9,15 @@ import 'package:flutter/material.dart'; /// 点击item回调 /// shareChannel 是分享渠道一般传入 [BrnShareItemConstants] 下的值 -typedef BrnShareDialogItemClickCallBack(int shareChannel, int customIndex); +typedef BrnShareDialogItemClickCallBack = void Function(int shareChannel, int customIndex); /// 获取自定义分享item标题 /// index为自定义分享item索引 -typedef String? BrnShareDialogGetCustomShareItemTitle(int index); +typedef BrnShareDialogGetCustomShareItemTitle = String? Function(int index); /// 获取自定义分享item图标 /// index为自定义分享item索引 -typedef Widget? BrnShareDialogGetCustomShareItemIcon(int index); +typedef BrnShareDialogGetCustomShareItemIcon = Widget? Function(int index); // ignore: must_be_immutable class BrnShareDialog extends StatelessWidget { diff --git a/lib/src/components/dialog/brn_single_select.dart b/lib/src/components/dialog/brn_single_select.dart index 1f3554e5..22bebc18 100644 --- a/lib/src/components/dialog/brn_single_select.dart +++ b/lib/src/components/dialog/brn_single_select.dart @@ -53,6 +53,9 @@ class BrnSingleSelectDialog extends Dialog { /// 是否在点击时让 Diallog 消失,默认为 true final bool canDismissOnConfirmClick; + /// 点击关闭按钮回调 + final VoidCallback? onCloseClick; + const BrnSingleSelectDialog( {this.isClose: true, this.title: "", @@ -65,6 +68,7 @@ class BrnSingleSelectDialog extends Dialog { this.onItemClick, this.checkedItem, this.customWidget, + this.onCloseClick, this.canDismissOnConfirmClick = true, this.isCustomFollowScroll = true}); @@ -83,7 +87,8 @@ class BrnSingleSelectDialog extends Dialog { checkedItem: checkedItem, customWidget: customWidget, canDismissOnConfirmClick: canDismissOnConfirmClick, - isCustomFollowScroll: isCustomFollowScroll); + isCustomFollowScroll: isCustomFollowScroll, + onCloseClick: onCloseClick,); } } @@ -106,6 +111,9 @@ class BrnSingleSelectDialogWidget extends StatefulWidget { final bool canDismissOnConfirmClick; + /// 点击关闭按钮回调 + final VoidCallback? onCloseClick; + BrnDialogConfig? themeData; BrnSingleSelectDialogWidget( @@ -120,6 +128,7 @@ class BrnSingleSelectDialogWidget extends StatefulWidget { this.onItemClick, this.checkedItem, this.customWidget, + this.onCloseClick, this.isCustomFollowScroll = true, this.canDismissOnConfirmClick = true, this.themeData}) { @@ -254,14 +263,18 @@ class BrnSingleSelectDialogWidgetState right: 0.0, child: InkWell( onTap: () { - Navigator.of(context).pop(); + if (widget.onCloseClick != null) { + widget.onCloseClick!(); + } else { + Navigator.of(context).pop(); + } }, child: Padding( padding: EdgeInsets.all(15), child: BrunoTools.getAssetImage( BrnAsset.iconPickerClose), ))) - : Container() + : SizedBox.shrink() ], ), ))); @@ -271,11 +284,12 @@ class BrnSingleSelectDialogWidgetState /// 若无则以 messageText 生成widget 填充, /// 都没设置则为空 Container Widget _generateContentWidget() { - if (widget.messageWidget != null) + if (widget.messageWidget != null) { return Padding( padding: EdgeInsets.only(bottom: 8, left: 20, right: 20), child: widget.messageWidget, ); + } if (!BrunoTools.isEmpty(widget.messageText)) { return Padding( diff --git a/lib/src/components/form/base/brn_form_item_type.dart b/lib/src/components/form/base/brn_form_item_type.dart index ffeeacc1..6fd1cc43 100644 --- a/lib/src/components/form/base/brn_form_item_type.dart +++ b/lib/src/components/form/base/brn_form_item_type.dart @@ -44,6 +44,7 @@ class BrnInputItemType { static const String labelTitle = "label_title"; static const String labelAdd = "label_add"; + static const String labelGeneralType = "label_general_type"; } class BrnInputType { diff --git a/lib/src/components/form/items/general/brn_quick_select_input_item.dart b/lib/src/components/form/items/general/brn_quick_select_input_item.dart index 917b1a3a..1dc06f97 100644 --- a/lib/src/components/form/items/general/brn_quick_select_input_item.dart +++ b/lib/src/components/form/items/general/brn_quick_select_input_item.dart @@ -322,7 +322,7 @@ class QuickButtonsState extends State { ); } } else { - return SizedBox.shrink(); + return const SizedBox.shrink(); } } diff --git a/lib/src/components/form/items/general/brn_step_input_item.dart b/lib/src/components/form/items/general/brn_step_input_item.dart index ce7f0ee1..0162a526 100644 --- a/lib/src/components/form/items/general/brn_step_input_item.dart +++ b/lib/src/components/form/items/general/brn_step_input_item.dart @@ -2,6 +2,7 @@ import 'package:bruno/bruno.dart'; import 'package:bruno/src/components/form/utils/brn_form_util.dart'; import 'package:bruno/src/constants/brn_fonts_constants.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; /// /// 递增/递减型录入项 @@ -63,6 +64,11 @@ class BrnStepInputFormItem extends StatefulWidget { /// 当前值变化回调 final OnBrnFormValueChanged? onChanged; + /// 是否可通过键盘手动输入内容 + final bool canManualInput; + + final TextEditingController? controller; + /// form配置 BrnFormItemConfig? themeData; @@ -83,9 +89,18 @@ class BrnStepInputFormItem extends StatefulWidget { this.maxLimit = 10, this.minLimit = 0, this.onChanged, + this.canManualInput = false, + this.controller, this.themeData, - }) : assert(value == null || value >= minLimit && value <= maxLimit), - super(key: key) { + }) : super(key: key) { + if (value != null) { + assert(value! >= minLimit && value! <= maxLimit); + } + if (controller != null) { + int? defaultValue = int.tryParse(controller!.text); + assert(defaultValue == null || (defaultValue >= minLimit && defaultValue <= maxLimit), + 'The text or value in the controller is not in the limits.'); + } this.themeData ??= BrnFormItemConfig(); this.themeData = BrnThemeConfigurator.instance .getConfig(configId: this.themeData!.configId) @@ -100,12 +115,33 @@ class BrnStepInputFormItem extends StatefulWidget { } class BrnStepInputFormItemState extends State { - late int _value; - + late TextEditingController _textEditingController; + late int _oldValue; @override void initState() { super.initState(); - _value = widget.value ?? widget.minLimit; + if (widget.controller == null) { + _textEditingController = TextEditingController(); + _textEditingController.text = (widget.value ?? 0).toString(); + } else { + _textEditingController = widget.controller!; + } + _oldValue = _value; + _textEditingController.addListener(_onControllerTextChangedHandleTicker); + } + + @override + void dispose() { + _textEditingController.removeListener(_onControllerTextChangedHandleTicker); + super.dispose(); + } + + void _onControllerTextChangedHandleTicker() { + if (_oldValue != _value) { + BrnFormUtil.notifyValueChanged(widget.onChanged, context, _oldValue, _value); + setState(() {}); + _oldValue = _value; + } } @override @@ -124,19 +160,14 @@ class BrnStepInputFormItemState extends State { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Container( - padding: BrnFormUtil.titleEdgeInsets(widget.prefixIconType, - widget.isRequire, widget.themeData!), + padding: BrnFormUtil.titleEdgeInsets( + widget.prefixIconType, widget.isRequire, widget.themeData!), child: Row( children: [ - BrnFormUtil.buildPrefixIcon( - widget.prefixIconType, - widget.isEdit, - context, - widget.onAddTap, - widget.onRemoveTap), + BrnFormUtil.buildPrefixIcon(widget.prefixIconType, widget.isEdit, context, + widget.onAddTap, widget.onRemoveTap), BrnFormUtil.buildRequireWidget(widget.isRequire), - BrnFormUtil.buildTitleWidget( - widget.title, widget.themeData!), + BrnFormUtil.buildTitleWidget(widget.title, widget.themeData!), BrnFormUtil.buildTipLabelWidget( widget.tipLabel, widget.onTip, widget.themeData!), ], @@ -147,55 +178,25 @@ class BrnStepInputFormItemState extends State { children: [ GestureDetector( onTap: () { - if (!isEnable()) { + if (!widget.isEdit) { return; } - - if (isReachMinLevel()) { - return; - } - - if (!isReachMinLevel()) { - _value = _value - 1; - BrnFormUtil.notifyValueChanged( - widget.onChanged, context, _value + 1, _value); - setState(() {}); - } + _checkReachMinLevel(); }, child: Container( - child: getMinusIcon(), - ), - ), - Container( - alignment: Alignment.center, - width: 50, - child: Text( - "$_value", - style: TextStyle( - color: Color(0xFF222222), - fontSize: BrnFonts.f16, - ), + child: _getMinusIcon(), ), ), + _buildValueWidget(), GestureDetector( onTap: () { - if (!isEnable()) { + if (!widget.isEdit) { return; } - - if (isReachMaxLevel()) { - return; - } - - if (!isReachMaxLevel()) { - _value = _value + 1; - BrnFormUtil.notifyValueChanged( - widget.onChanged, context, _value - 1, _value); - setState(() {}); - } + _checkReachMaxLevel(); }, child: Container( - child: getAddIcon(), + child: _getAddIcon(), ), ), ], @@ -213,45 +214,126 @@ class BrnStepInputFormItemState extends State { ); } - bool isEnable() { - return widget.isEdit; - } - - Image getAddIcon() { + Image _getAddIcon() { if (!widget.isEdit) { return BrunoTools.getAssetImage(BrnAsset.iconAddDisable); } - if (isReachMaxLevel()) { + if (_isReachMaxLevel()) { return BrunoTools.getAssetImage(BrnAsset.iconAddDisable); } return BrunoTools.getAssetImage(BrnAsset.iconAddEnable); } - bool isReachMaxLevel() { + bool _isReachMaxLevel() { if (_value >= widget.maxLimit) { return true; } return false; } - Image getMinusIcon() { + Image _getMinusIcon() { if (!widget.isEdit) { return BrunoTools.getAssetImage(BrnAsset.iconMinusDisable); } - if (isReachMinLevel()) { + if (_isReachMinLevel()) { return BrunoTools.getAssetImage(BrnAsset.iconMinusDisable); } return BrunoTools.getAssetImage(BrnAsset.iconMinusEnable); } - bool isReachMinLevel() { + bool _isReachMinLevel() { if (_value <= widget.minLimit) { return true; } return false; } + + Widget _buildValueWidget() { + if (widget.canManualInput) { + return Container( + alignment: Alignment.center, + width: 50, + child: TextField( + maxLines: 1, + minLines: 1, + enabled: widget.isEdit, + textAlign: TextAlign.center, + controller: _textEditingController, + inputFormatters: [ + FilteringTextInputFormatter.digitsOnly, + RangeLimitedTextInputFormatter(minValue: widget.minLimit, maxValue: widget.maxLimit) + ], + style: TextStyle( + color: Color(0xFF222222), + fontSize: BrnFonts.f16, + ), + decoration: InputDecoration( + hintText: '0', + hintStyle: TextStyle( + color: Color(0xFFCCCCCC), + fontSize: BrnFonts.f16, + ), + border: InputBorder.none, + contentPadding: EdgeInsets.all(0), + isDense: true, + ), + ), + ); + } else { + return Container( + alignment: Alignment.center, + width: 50, + child: Text( + "$_value", + style: TextStyle( + color: Color(0xFF222222), + fontSize: BrnFonts.f16, + ), + ), + ); + } + } + + void _checkReachMinLevel() { + if (!_isReachMinLevel()) { + _value = _value - 1; + return; + } + } + + void _checkReachMaxLevel() { + if (!_isReachMaxLevel()) { + _value = _value + 1; + return; + } + } + + int get _value => int.tryParse(_textEditingController.text) ?? 0; + + set _value(int value) { + _textEditingController.text = value.toString(); + } +} + +class RangeLimitedTextInputFormatter extends TextInputFormatter { + int minValue; + int maxValue; + + RangeLimitedTextInputFormatter({this.minValue = 0, this.maxValue = 0}); + + @override + TextEditingValue formatEditUpdate(TextEditingValue oldValue, TextEditingValue newValue) { + int? newNum = int.tryParse(newValue.text); + if(newNum == null && minValue == 0) { + return TextEditingValue(text: ''); + } else if (newNum != null && minValue <= newNum && newNum <= maxValue) { + return TextEditingValue(text: newNum.toString()); + } else { + return oldValue; + } + } } diff --git a/lib/src/components/form/items/general/brn_switch_item.dart b/lib/src/components/form/items/general/brn_switch_item.dart new file mode 100644 index 00000000..fe9e584c --- /dev/null +++ b/lib/src/components/form/items/general/brn_switch_item.dart @@ -0,0 +1,210 @@ +import 'package:bruno/src/components/form/base/brn_form_item_type.dart'; +import 'package:bruno/src/components/form/base/input_item_interface.dart'; +import 'package:bruno/src/components/form/utils/brn_form_util.dart'; +import 'package:bruno/src/components/switch/brn_switch_button.dart'; +import 'package:bruno/src/theme/brn_theme.dart'; +import 'package:flutter/material.dart'; + +/// 带开关按钮表单 +// ignore: must_be_immutable +class BrnSwitchFormItem extends StatefulWidget { + + /// 录入项的唯一标识,主要用于录入类型页面框架中 + final String? label; + + /// 录入项类型,主要用于录入类型页面框架中 + final String type = BrnInputItemType.switchType; + + /// 录入项标题 + final String title; + + /// 录入项子标题 + final String? subTitle; + + /// 录入项提示(问号图标&文案) 用户点击时触发onTip回调。 + /// 1. 若赋值为 空字符串("")时仅展示"问号"图标, + /// 2. 若赋值为非空字符串时 展示"问号图标&文案", + /// 3. 若不赋值或赋值为null时 不显示提示项 + /// 默认值为 3 + final String? tipLabel; + + /// 录入项前缀图标样式 "添加项" "删除项" 详见 PrefixIconType类 + final String prefixIconType; + + /// 录入项错误提示 + final String error; + + /// 录入项是否为必填项(展示*图标) 默认为 false 不必填 + final bool isRequire; + + /// 录入项 是否可编辑 + final bool isEdit; + + /// 点击"+"图标回调 + final VoidCallback? onAddTap; + + /// 点击"-"图标回调 + final VoidCallback? onRemoveTap; + + /// 点击"?"图标回调 + final VoidCallback? onTip; + + /// 特有字段 + final bool value; + + /// 开关变化回调 + final OnBrnFormSwitchChanged? onChanged; + + /// form配置 + BrnFormItemConfig? themeData; + + BrnSwitchFormItem({ + Key? key, + this.label, + this.title = "", + this.subTitle, + this.tipLabel, + this.prefixIconType = BrnPrefixIconType.normal, + this.error= "", + this.isEdit = true, + this.isRequire = true, + this.onAddTap, + this.onRemoveTap, + this.onTip, + required this.value, + this.onChanged, + this.themeData, + }) : super() { + this.themeData ??= BrnFormItemConfig(); + this.themeData = BrnThemeConfigurator.instance + .getConfig(configId: this.themeData!.configId) + .formItemConfig + .merge(this.themeData); + } + + @override + BrnSwitchFormItemState createState() { + return BrnSwitchFormItemState(); + } +} + +class BrnSwitchFormItemState extends State { + + @override + Widget build(BuildContext context) { + return Container( + color: Colors.white, + padding: BrnFormUtil.itemEdgeInsets(widget.themeData!), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ConstrainedBox( + constraints: BoxConstraints( + maxHeight: 25, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + + Container( + padding: BrnFormUtil.titleEdgeInsets(widget.prefixIconType, widget.isRequire,widget.themeData!), + child: Row( + children: [ + + Offstage( + offstage: (widget.prefixIconType == BrnPrefixIconType.normal), + child: Container( + padding: EdgeInsets.only(right: 6), + child: GestureDetector( + onTap: () { + + if (!BrnFormUtil.isEdit(widget.isEdit)) { + return; + } + + BrnFormUtil.notifyAddRemoveTap(context,widget.prefixIconType, widget.onAddTap, widget.onRemoveTap); + + }, + child: BrnFormUtil.getPrefixIcon(widget.prefixIconType), + ), + ), + ), + + Offstage( + offstage: (!widget.isRequire), + child: BrnFormUtil.getRequireIcon(widget.isRequire), + ), + Container( + child: Text(widget.title, style: BrnFormUtil.getTitleTextStyle(widget.themeData!),) + ), + + Offstage( + offstage: (widget.tipLabel == null), + child: GestureDetector( + onTap: () { + if (widget.onTip != null) { + widget.onTip!(); + } + }, + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Container( + padding: EdgeInsets.only(left:6, right: 7), + child: BrnFormUtil.getQuestionMarkIcon() + ), + + Container( + child: Text(widget.tipLabel ?? "", style: BrnFormUtil.getTipsTextStyle(widget.themeData!),), + ), + ], + ), + ), + ), + + ], + ), + ), + BrnSwitchButton( + size: Size(42,25), + value: widget.value, + enabled: widget.isEdit, + onChanged: (bool value) { + bool oldValue = widget.value; + BrnFormUtil.notifySwitchChanged(widget.onChanged, context, oldValue, value); + setState(() {}); + }, + ), + ], + ), + ), + + /// 副标题 + Offstage( + offstage: (widget.subTitle == null || widget.subTitle!.isEmpty), + child: Container( + padding: BrnFormUtil.subTitleEdgeInsets(widget.themeData!), + child: Text(widget.subTitle ?? "", style: BrnFormUtil.getSubTitleTextStyle(widget.themeData!),)), + ), + + Offstage( + offstage: (widget.error.isEmpty), + child: Container( + padding: BrnFormUtil.errorEdgeInsets(widget.themeData!), + child: Text(widget.error, style: BrnFormUtil.getErrorTextStyle(widget.themeData!),), + ), + ) + ], + ), + + ); + } + +} + + + + + + + diff --git a/lib/src/components/form/items/general/brn_text_block_input_item.dart b/lib/src/components/form/items/general/brn_text_block_input_item.dart index 3bc7699d..210a2615 100644 --- a/lib/src/components/form/items/general/brn_text_block_input_item.dart +++ b/lib/src/components/form/items/general/brn_text_block_input_item.dart @@ -66,6 +66,9 @@ class BrnTextBlockInputFormItem extends StatefulWidget { /// 输入内容类型 final String? inputType; + /// 是否自动获取焦点 + bool autofocus; + /// 指定对输入数据的格式化要求 final List? inputFormatters; @@ -75,10 +78,10 @@ class BrnTextBlockInputFormItem extends StatefulWidget { final TextEditingController? controller; /// 最小行数,默认值4 - final int minLines; + final int? minLines; /// 最大行数,默认值20 - final int maxLines; + final int? maxLines; /// form配置 BrnFormItemConfig? themeData; @@ -100,6 +103,7 @@ class BrnTextBlockInputFormItem extends StatefulWidget { this.onChanged, this.hint = "请输入", this.maxCharCount, + this.autofocus: false, this.inputType, this.inputFormatters, this.controller, @@ -176,6 +180,7 @@ class BrnTextBlockInputFormItemState extends State { Container( padding: BrnFormUtil.errorEdgeInsets(widget.themeData!), child: TextField( + autofocus: widget.autofocus, keyboardType: BrnFormUtil.getInputType(widget.inputType), controller: _controller, maxLength: widget.maxCharCount, diff --git a/lib/src/components/form/items/general/brn_text_input_item.dart b/lib/src/components/form/items/general/brn_text_input_item.dart index d5580025..f2fde8fd 100644 --- a/lib/src/components/form/items/general/brn_text_input_item.dart +++ b/lib/src/components/form/items/general/brn_text_input_item.dart @@ -71,6 +71,9 @@ class BrnTextInputFormItem extends StatefulWidget { /// 输入内容类型 final String? inputType; + /// 是否自动获取焦点 + bool autofocus; + /// 最大可输入字符数 final int? maxCharCount; final List? inputFormatters; @@ -101,6 +104,7 @@ class BrnTextInputFormItem extends StatefulWidget { this.hint = "请输入", this.unit, this.maxCharCount, + this.autofocus: false, this.inputType, this.inputFormatters, this.onChanged, @@ -174,6 +178,7 @@ class BrnTextInputFormItemState extends State { ), Expanded( child: TextField( + autofocus: widget.autofocus, keyboardType: BrnFormUtil.getInputType(widget.inputType), enabled: widget.isEdit, maxLines: 1, diff --git a/lib/src/components/form/items/general/brn_title_select_input_item.dart b/lib/src/components/form/items/general/brn_title_select_input_item.dart index 4410cb96..ab24bb09 100644 --- a/lib/src/components/form/items/general/brn_title_select_input_item.dart +++ b/lib/src/components/form/items/general/brn_title_select_input_item.dart @@ -74,6 +74,9 @@ class BrnTitleSelectInputFormItem extends StatefulWidget { /// 输入类型 final String inputType; + /// 是否自动获取焦点 + bool autofocus; + /// 选中title索引 final int selectedIndex; @@ -111,6 +114,7 @@ class BrnTitleSelectInputFormItem extends StatefulWidget { this.inputType = BrnInputType.text, this.selectedIndex = -1, this.inputFormatters, + this.autofocus: false, this.onChanged, this.onTitleSelected, this.controller, @@ -284,6 +288,7 @@ class BrnTitleSelectInputFormItemState Widget _buildTextField() { return TextField( + autofocus: widget.autofocus, inputFormatters: widget.inputFormatters, textAlign: TextAlign.end, controller: _controller, diff --git a/lib/src/components/form/items/group/brn_expandable_group.dart b/lib/src/components/form/items/group/brn_expandable_group.dart index 33419c5b..d9321482 100644 --- a/lib/src/components/form/items/group/brn_expandable_group.dart +++ b/lib/src/components/form/items/group/brn_expandable_group.dart @@ -10,7 +10,6 @@ import 'package:bruno/src/theme/brn_theme_configurator.dart'; import 'package:bruno/src/theme/configs/brn_form_config.dart'; import 'package:bruno/src/utils/brn_tools.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/widgets.dart'; /// A single-line [ListTile] with a trailing button that expands or collapses /// the tile to reveal or hide the [children]. @@ -150,8 +149,9 @@ class _BrnExpansionElementState extends State } PageStorage.of(context)?.writeState(context, _isExpanded); }); - if (widget.onExpansionChanged != null) + if (widget.onExpansionChanged != null) { widget.onExpansionChanged!(_isExpanded); + } } Widget _buildHeader(BuildContext context, Widget? child) { diff --git a/lib/src/components/form/items/group/brn_portrait_radio_group.dart b/lib/src/components/form/items/group/brn_portrait_radio_group.dart index f66df326..e48430b0 100644 --- a/lib/src/components/form/items/group/brn_portrait_radio_group.dart +++ b/lib/src/components/form/items/group/brn_portrait_radio_group.dart @@ -157,7 +157,7 @@ class BrnPortraitRadioGroupState extends State { }, ), Visibility( - visible: option.subTitle != null && option.subTitle!.length > 0, + visible: option.subTitle != null && option.subTitle!.isNotEmpty, child: Padding( padding: EdgeInsets.only(top: 4, right: 20), child: Text( diff --git a/lib/src/components/form/items/group/element_expand_widget.dart b/lib/src/components/form/items/group/element_expand_widget.dart index 2d082ed1..af4f56ae 100644 --- a/lib/src/components/form/items/group/element_expand_widget.dart +++ b/lib/src/components/form/items/group/element_expand_widget.dart @@ -10,7 +10,6 @@ import 'package:bruno/src/theme/configs/brn_form_config.dart'; import 'package:bruno/src/utils/brn_tools.dart'; import 'package:bruno/src/constants/brn_fonts_constants.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/widgets.dart'; /// A single-line [ListTile] with a trailing button that expands or collapses /// the tile to reveal or hide the [children]. @@ -163,8 +162,9 @@ class _ExpansionElementState extends State } PageStorage.of(context)?.writeState(context, _isExpanded); }); - if (widget.onExpansionChanged != null) + if (widget.onExpansionChanged != null) { widget.onExpansionChanged!(_isExpanded); + } } Widget _buildHeader(BuildContext context, Widget? child) { diff --git a/lib/src/components/form/items/misc/brn_general_item.dart b/lib/src/components/form/items/misc/brn_general_item.dart new file mode 100644 index 00000000..af3cd8b2 --- /dev/null +++ b/lib/src/components/form/items/misc/brn_general_item.dart @@ -0,0 +1,216 @@ +import 'package:bruno/src/components/form/base/brn_form_item_type.dart'; +import 'package:bruno/src/components/form/utils/brn_form_util.dart'; +import 'package:bruno/src/theme/brn_theme.dart'; +import 'package:flutter/material.dart'; + +// ignore: must_be_immutable +class BrnGeneralFormItem extends StatefulWidget{ + + /// 录入项的唯一标识,主要用于录入类型页面框架中 + final String? label; + + /// 录入项类型,主要用于录入类型页面框架中 + final String type = BrnInputItemType.labelGeneralType; + + /// 录入项标题 + final String title; + + /// 录入项子标题 + final Widget? titleWidget; + + /// 录入项子标题 + final String? subTitle; + + /// 录入项子标题 widget + final Widget? subTitleWidget; + + /// 录入项提示(问号图标&文案) 用户点击时触发onTip回调。 + /// 1. 若赋值为 空字符串("")时仅展示"问号"图标, + /// 2. 若赋值为非空字符串时 展示"问号图标&文案", + /// 3. 若不赋值或赋值为null时 不显示提示项 + /// 默认值为 3 + final String? tipLabel; + + /// 录入项前缀图标样式 "添加项" "删除项" 详见 PrefixIconType类 + final String prefixIconType; + + /// 录入项错误提示 + final String error; + + /// 录入项是否为必填项(展示*图标) 默认为 false 不必填 + final bool isRequire; + + /// 录入项 是否可编辑 + final bool isEdit; + + /// 点击"+"图标回调 + final VoidCallback? onAddTap; + + /// 点击"-"图标回调 + final VoidCallback? onRemoveTap; + + /// 点击"?"图标回调 + final VoidCallback? onTip; + + /// 右侧操作widget + final Widget? operateWidget; + + /// form配置 + BrnFormItemConfig? themeData; + + BrnGeneralFormItem({ + Key? key, + this.label, + this.title: "", + this.titleWidget, + this.subTitle, + this.subTitleWidget, + this.tipLabel, + this.prefixIconType = BrnPrefixIconType.normal, + this.error: "", + this.isEdit: true, + this.isRequire: false, + this.operateWidget, + this.onAddTap, + this.onRemoveTap, + this.onTip, + this.themeData, + }): super(key: key){ + this.themeData ??= BrnFormItemConfig(); + this.themeData = BrnThemeConfigurator.instance + .getConfig(configId: this.themeData!.configId) + .formItemConfig + .merge(this.themeData); + } + + @override + State createState() { + return BrnGeneralFormItemState(); + } + +} + +class BrnGeneralFormItemState extends State { + + @override + Widget build(BuildContext context) { + + return Container( + color: Colors.white, + padding: BrnFormUtil.itemEdgeInsets(widget.themeData!), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + padding: BrnFormUtil.titleEdgeInsets(widget.prefixIconType, + widget.isRequire, widget.themeData!), + child: Row( + children: [ + + Offstage( + offstage: widget.prefixIconType == BrnPrefixIconType.normal, + child: Container( + padding: EdgeInsets.only(right: 6), + child: GestureDetector( + onTap: () { + + if ( !widget.isEdit) { + return; + } + + if (BrnPrefixIconType.add == widget.prefixIconType) { + if (widget.onAddTap != null) { + widget.onAddTap!(); + } + } else if (BrnPrefixIconType.remove == widget.prefixIconType) { + if (widget.onRemoveTap != null) { + widget.onRemoveTap!(); + } + } + + }, + child: BrnFormUtil.getPrefixIcon(widget.prefixIconType), + ), + ), + ), + + Offstage( + offstage: (!widget.isRequire), + child: BrnFormUtil.getRequireIcon(widget.isRequire), + ), + Container( + child: widget.titleWidget ?? Text(widget.title, style: BrnFormUtil.getTitleTextStyle(widget.themeData!),) + ), + + Offstage( + offstage: (widget.tipLabel == null), + child: GestureDetector( + onTap: () { + + if (widget.onTip != null) { + widget.onTip!(); + } + }, + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Container( + padding: EdgeInsets.only(left:6, right: 7), + child: BrnFormUtil.getQuestionMarkIcon() + ), + + Container( + child: Text(widget.tipLabel ?? "", style: BrnFormUtil.getTipsTextStyle(widget.themeData!),), + ), + ], + ), + ), + ), + + ], + ), + ), + + + Container( + child: widget.operateWidget ?? SizedBox.shrink(), + ), + + ], + ), + + Offstage( + offstage: ((widget.subTitleWidget == null) && (widget.subTitle == null || widget.subTitle!.isEmpty)), + child: Container( + padding: BrnFormUtil.subTitleEdgeInsets(widget.themeData!), + child: widget.subTitleWidget ?? Text(widget.subTitle ?? "", style: BrnFormUtil.getSubTitleTextStyle(widget.themeData!),)), + ), + + Offstage( + offstage: (widget.error.isEmpty), + child: Container( + padding: BrnFormUtil.computeErrorEdgeInsets(widget.prefixIconType, widget.isRequire), + child: Text(widget.error, style: BrnFormUtil.getErrorTextStyle(widget.themeData!),)) + ) + ], + ), + + ); + + + } + + +} + + + + + + + + + diff --git a/lib/src/components/form/items/misc/brn_title_item.dart b/lib/src/components/form/items/misc/brn_title_item.dart index 7c786007..6582b5cf 100644 --- a/lib/src/components/form/items/misc/brn_title_item.dart +++ b/lib/src/components/form/items/misc/brn_title_item.dart @@ -100,6 +100,8 @@ class BrnTitleFormItemState extends State { widget.isRequire, widget.themeData!), child: Row( children: [ + // 必填项 + BrnFormUtil.buildRequireWidget(widget.isRequire), // 主标题 Container( child: Text( @@ -107,7 +109,6 @@ class BrnTitleFormItemState extends State { style: BrnFormUtil.getHeadTitleTextStyle( widget.themeData!), )), - // 问号提示 BrnFormUtil.buildTipLabelWidget( widget.tipLabel, widget.onTip, widget.themeData!), diff --git a/lib/src/components/gallery/page/brn_gallery_detail_page.dart b/lib/src/components/gallery/page/brn_gallery_detail_page.dart index 829bb00f..fa1573a5 100644 --- a/lib/src/components/gallery/page/brn_gallery_detail_page.dart +++ b/lib/src/components/gallery/page/brn_gallery_detail_page.dart @@ -22,10 +22,10 @@ class BrnGalleryDetailPage extends StatefulWidget { final List allConfig; /// 初始位于第几组,默认 0 - final initGroupId; + final int initGroupId; /// 初始位于组内的第几个,默认 0 - final initIndexId; + final int initIndexId; /// 是否来自于列表页,一般情况不要使用,默认 false final bool fromSummary; @@ -188,7 +188,7 @@ class _BrnGalleryDetailPageState extends State _allConfig.forEach((item) => _tabs.add( BadgeTab(text: '${item.title ?? ""}(${item.configList!.length})'))); - if (_allConfig.length > 1) + if (_allConfig.length > 1) { _columnViews.add(BrnTabBar( backgroundcolor: _tabBarConfig.backgroundColor, unselectedLabelStyle: @@ -204,6 +204,7 @@ class _BrnGalleryDetailPageState extends State duration: Duration(microseconds: 100), curve: Curves.linear); }, )); + } for (int i = 0; i < _allConfig.length; i++) { for (int j = 0; j < _allConfig[i].configList!.length; j++) { diff --git a/lib/src/components/gallery/page/brn_gallery_summary_page.dart b/lib/src/components/gallery/page/brn_gallery_summary_page.dart index 2e7d7c93..30e07e9e 100644 --- a/lib/src/components/gallery/page/brn_gallery_summary_page.dart +++ b/lib/src/components/gallery/page/brn_gallery_summary_page.dart @@ -99,7 +99,7 @@ class _BrnGallerySummaryPageState extends State { Widget _buildItem(BrnBasicGroupConfig? groupConfig, int groupId) { if (groupConfig == null) return Row(); List columnViews = []; - if (groupConfig.title != null) + if (groupConfig.title != null) { columnViews.add(Container( height: 53, child: Padding( @@ -113,15 +113,16 @@ class _BrnGallerySummaryPageState extends State { ), ), )); + } if (groupConfig.configList != null) { List gridViews = []; - for (int i = 0; i < groupConfig.configList!.length; i++) + for (int i = 0; i < groupConfig.configList!.length; i++) { gridViews.add(GestureDetector( onTap: () { //页面的跳转不应该交个子Widget处理 - if (widget.fromDetail) + if (widget.fromDetail) { Navigator.of(context).pop([groupId, i]); - else + } else { Navigator.of(context).push(CupertinoPageRoute(builder: (context) { return BrnGalleryDetailPage( allConfig: widget.allConfig, @@ -132,10 +133,12 @@ class _BrnGallerySummaryPageState extends State { controller: widget.controller, ); })); + } }, child: groupConfig.configList![i] .buildSummaryWidget(context, widget.allConfig, groupId, i), )); + } columnViews.add(GridView.count( physics: NeverScrollableScrollPhysics(), shrinkWrap: true, diff --git a/lib/src/components/guide/brn_tip_widget.dart b/lib/src/components/guide/brn_tip_widget.dart index d8e1f094..d1cefe3b 100644 --- a/lib/src/components/guide/brn_tip_widget.dart +++ b/lib/src/components/guide/brn_tip_widget.dart @@ -48,7 +48,7 @@ class BrnTipInfoWidget extends StatelessWidget { Color borderColor = mode == GuideMode.force ? Colors.transparent : Color(0xFFCCCCCC); if (direction == GuideDirection.bottomLeft || - direction == GuideDirection.bottomRight) + direction == GuideDirection.bottomRight) { return Column( verticalDirection: VerticalDirection.up, children: [ @@ -70,8 +70,9 @@ class BrnTipInfoWidget extends StatelessWidget { ), ], ); + } if (direction == GuideDirection.topLeft || - direction == GuideDirection.topRight) + direction == GuideDirection.topRight) { return Column( children: [ buildContent(), @@ -90,7 +91,8 @@ class BrnTipInfoWidget extends StatelessWidget { ), ], ); - if (direction == GuideDirection.left) + } + if (direction == GuideDirection.left) { return Row( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, @@ -107,7 +109,8 @@ class BrnTipInfoWidget extends StatelessWidget { ), ], ); - if (direction == GuideDirection.right) + } + if (direction == GuideDirection.right) { return Row( crossAxisAlignment: CrossAxisAlignment.end, textDirection: TextDirection.rtl, @@ -127,6 +130,7 @@ class BrnTipInfoWidget extends StatelessWidget { ), ], ); + } return Row(); } diff --git a/lib/src/components/navbar/brn_appbar.dart b/lib/src/components/navbar/brn_appbar.dart index 93ee65b5..6f9b2746 100644 --- a/lib/src/components/navbar/brn_appbar.dart +++ b/lib/src/components/navbar/brn_appbar.dart @@ -136,7 +136,7 @@ class BrnAppBar extends PreferredSize { final VoidCallback? backLeadCallback; /// 是否显示默认的eeeeee分割线,默认显示,可以设置为不显示 - final bool showDefaultBottom; + final bool? showDefaultBottom; final bool showLeadingDivider; final BrnAppBarConfig? themeData; @@ -156,7 +156,7 @@ class BrnAppBar extends PreferredSize { this.titleAlignment = Alignment.center, this.flexibleSpace, this.backLeadCallback, - this.showDefaultBottom = true, + this.showDefaultBottom, this.themeData, this.leadingWidth, this.shadowColor, @@ -233,7 +233,7 @@ class BrnAppBar extends PreferredSize { _defaultConfig = _defaultConfig.merge(BrnAppBarConfig.dark()); } _defaultConfig = _defaultConfig - .merge(BrnAppBarConfig(backgroundColor: this.backgroundColor)); + .merge(BrnAppBarConfig(backgroundColor: this.backgroundColor, showDefaultBottom: this.showDefaultBottom)); _defaultConfig = BrnThemeConfigurator.instance .getConfig(configId: _defaultConfig.configId) @@ -246,9 +246,9 @@ class BrnAppBar extends PreferredSize { return super.build(context); } - PreferredSizeWidget? _buildBarBottom() { + PreferredSizeWidget? _buildBarBottom(BrnAppBarConfig defaultConfig) { if (brightness == null || brightness == Brightness.light) { - if (bottom == null && showDefaultBottom) { + if (bottom == null && defaultConfig.showDefaultBottom) { return BrnBarBottomDivider(); } } @@ -292,7 +292,7 @@ class BrnAppBar extends PreferredSize { elevation: elevation, backgroundColor: _defaultConfig.backgroundColor, actions: _wrapActions(_defaultConfig), - bottom: _buildBarBottom(), + bottom: _buildBarBottom(_defaultConfig), brightness: brightness ?? Brightness.light, toolbarOpacity: toolbarOpacity, bottomOpacity: bottomOpacity, @@ -592,13 +592,13 @@ class BrnBarBottomDivider extends PreferredSize { class _BrnSearchResultAppBar extends StatelessWidget { final BrnAppBarConfig? appBarConfig; final String? title; - final backgroundColor; - final bottom; - final brightness; - final showLeadingDivider; - final flexibleSpace; - final backLeadCallback; - final showDefaultBottom; + final Color? backgroundColor; + final PreferredSizeWidget? bottom; + final Brightness? brightness; + final bool showLeadingDivider; + final Widget? flexibleSpace; + final VoidCallback? backLeadCallback; + final bool? showDefaultBottom; _BrnSearchResultAppBar( {this.appBarConfig, @@ -622,7 +622,11 @@ class _BrnSearchResultAppBar extends StatelessWidget { } _defaultConfig = _defaultConfig - .merge(BrnAppBarConfig(backgroundColor: this.backgroundColor)); + .merge(BrnAppBarConfig( + backgroundColor: this.backgroundColor, + showDefaultBottom: this.showDefaultBottom, + )); + _defaultConfig = BrnThemeConfigurator.instance .getConfig(configId: _defaultConfig.configId) .appBarConfig @@ -639,7 +643,7 @@ class _BrnSearchResultAppBar extends StatelessWidget { /// divider Visibility( - visible: showLeadingDivider ?? true, + visible: showLeadingDivider, child: Container( margin: EdgeInsets.only(left: 12, right: 12), height: 16, @@ -650,7 +654,7 @@ class _BrnSearchResultAppBar extends StatelessWidget { /// padding Visibility( - visible: !(showLeadingDivider ?? true), + visible: !(showLeadingDivider), child: Padding( padding: EdgeInsets.only(left: 12), ), diff --git a/lib/src/components/picker/base/brn_picker.dart b/lib/src/components/picker/base/brn_picker.dart index c44c3037..3776a810 100644 --- a/lib/src/components/picker/base/brn_picker.dart +++ b/lib/src/components/picker/base/brn_picker.dart @@ -8,7 +8,6 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/services.dart'; -import 'package:flutter/widgets.dart'; /// Color of the 'magnifier' lens border. const Color _kHighlighterBorder = Color(0xFFF0F0F0); @@ -425,10 +424,11 @@ class _RenderCupertinoPickerSemantics extends RenderProxyBox { set controller(FixedExtentScrollController? value) { if (value == _controller) return; - if (_controller != null) + if (_controller != null) { _controller!.removeListener(_handleScrollUpdate); - else + } else { _currentIndex = value!.initialItem; + } value?.addListener(_handleScrollUpdate); _controller = value; } @@ -469,8 +469,9 @@ class _RenderCupertinoPickerSemantics extends RenderProxyBox { @override void assembleSemanticsNode(SemanticsNode node, SemanticsConfiguration config, Iterable children) { - if (children.isEmpty) + if (children.isEmpty) { return super.assembleSemanticsNode(node, config, children); + } final SemanticsNode scrollable = children.first; final Map indexedChildren = {}; scrollable.visitChildren((SemanticsNode child) { diff --git a/lib/src/components/picker/brn_bottom_picker.dart b/lib/src/components/picker/brn_bottom_picker.dart index 91a531c9..65c7e9da 100644 --- a/lib/src/components/picker/brn_bottom_picker.dart +++ b/lib/src/components/picker/brn_bottom_picker.dart @@ -5,7 +5,6 @@ import 'package:bruno/src/components/picker/base/brn_picker_title_config.dart'; import 'package:bruno/src/components/picker/brn_picker_cliprrect.dart'; import 'package:bruno/src/theme/brn_theme_configurator.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/rendering.dart'; /// 该picker用于显示自定的底部弹出框: 对话框结构如下: /// column @@ -77,7 +76,7 @@ class BrnBottomPickerWidget extends StatefulWidget { final dynamic cancel; final Function()? onConfirmPressed; final Function()? onCancelPressed; - final barrierDismissible; + final bool barrierDismissible; final BrnPickerTitleConfig pickerTitleConfig; const BrnBottomPickerWidget({ diff --git a/lib/src/components/picker/brn_bottom_write_picker.dart b/lib/src/components/picker/brn_bottom_write_picker.dart index c5a5cbaf..e2027c7a 100644 --- a/lib/src/components/picker/brn_bottom_write_picker.dart +++ b/lib/src/components/picker/brn_bottom_write_picker.dart @@ -117,7 +117,7 @@ class _BottomWritePickerState extends State { void initState() { super.initState(); if (_controller == null) { - if (widget.defaultText != null && widget.defaultText!.length > 0) { + if (widget.defaultText != null && widget.defaultText!.isNotEmpty) { _controller = TextEditingController.fromValue(TextEditingValue( text: widget.defaultText!, selection: TextSelection.fromPosition(TextPosition( diff --git a/lib/src/components/picker/brn_mulit_select_tags_picker.dart b/lib/src/components/picker/brn_mulit_select_tags_picker.dart index dd16cff6..a1507a0f 100644 --- a/lib/src/components/picker/brn_mulit_select_tags_picker.dart +++ b/lib/src/components/picker/brn_mulit_select_tags_picker.dart @@ -3,8 +3,7 @@ import 'package:bruno/src/components/picker/base/brn_picker_title_config.dart'; import 'package:bruno/src/components/picker/brn_tags_common_picker.dart'; import 'package:bruno/src/components/picker/brn_tags_picker_config.dart'; -import 'package:bruno/src/theme/brn_theme_configurator.dart'; -import 'package:bruno/src/theme/configs/brn_picker_config.dart'; +import 'package:bruno/src/theme/brn_theme.dart'; import 'package:flutter/material.dart'; ///样式的枚举类型 @@ -217,22 +216,24 @@ class BrnMultiSelectTagsPicker extends CommonTagsPicker { ///流式布局 Widget _buildWrapViewWidget(BuildContext context, VoidCallback? onUpdate) { - Color selectedTagTitleColor = this.tagPickerConfig.selectedTagTitleColor ?? - BrnThemeConfigurator.instance.getConfig().commonConfig.brandPrimary; - Color tagTitleColor = this.tagPickerConfig.tagTitleColor ?? - BrnThemeConfigurator.instance - .getConfig() - .commonConfig - .colorTextImportant; - Color tagBackgroundColor = - this.tagPickerConfig.tagBackgroudColor ?? Color(0xffF8F8F8); - Color selectedTagBackgroundColor = - this.tagPickerConfig.selectedTagBackgroudColor ?? - BrnThemeConfigurator.instance - .getConfig() - .commonConfig - .brandPrimary - .withAlpha(0x14); + BrnTagConfig tagConfig = BrnThemeConfigurator.instance + .getConfig(configId: themeData!.configId) + .tagConfig + .merge(BrnTagConfig()); + tagConfig = tagConfig.merge(BrnTagConfig( + selectTagTextStyle: BrnTextStyle( + height: 1, + color: this.tagPickerConfig.selectedTagTitleColor, + fontSize: this.tagPickerConfig.tagTitleFontSize, + fontWeight: FontWeight.w600), + tagTextStyle: BrnTextStyle( + height: 1, + color: this.tagPickerConfig.tagTitleColor, + fontSize: this.tagPickerConfig.tagTitleFontSize, + fontWeight: FontWeight.w400), + tagBackgroundColor: this.tagPickerConfig.tagBackgroudColor, + selectedTagBackgroundColor: + this.tagPickerConfig.selectedTagBackgroudColor)); return Container( padding: EdgeInsets.symmetric(vertical: 16, horizontal: 16), @@ -240,16 +241,15 @@ class BrnMultiSelectTagsPicker extends CommonTagsPicker { spacing: 15.0, children: this._sourceTags.map((choice) { bool selected = choice.isSelect; - Color titleColor = selected ? selectedTagTitleColor : tagTitleColor; - EdgeInsets edgeInsets = this.tagPickerConfig.chipPadding ?? EdgeInsets.only(top: 9.0, left: 10.0, right: 10, bottom: 11.0); return ChoiceChip( selected: selected, padding: edgeInsets, pressElevation: 0, - backgroundColor: tagBackgroundColor, - selectedColor: selectedTagBackgroundColor, + backgroundColor: tagConfig.tagBackgroundColor, + selectedColor: tagConfig.selectedTagBackgroundColor + .withAlpha(0x14), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(2.0)), label: Text( @@ -257,11 +257,7 @@ class BrnMultiSelectTagsPicker extends CommonTagsPicker { textAlign: TextAlign.center, overflow: TextOverflow.ellipsis, strutStyle: StrutStyle(forceStrutHeight: true, height: 1), - style: TextStyle( - height: 1, - color: titleColor, - fontWeight: selected ? FontWeight.w600 : FontWeight.w400, - fontSize: this.tagPickerConfig.tagTitleFontSize), + style: TextStyle(color: Colors.grey), ), onSelected: (bool value) { if (_selectedTags.length > this.maxSelectItemCount && diff --git a/lib/src/components/picker/brn_multi_picker.dart b/lib/src/components/picker/brn_multi_picker.dart index 5b2ab14b..eed332bc 100644 --- a/lib/src/components/picker/brn_multi_picker.dart +++ b/lib/src/components/picker/brn_multi_picker.dart @@ -1,5 +1,3 @@ - - import 'package:bruno/src/components/picker/base/brn_picker.dart'; import 'package:bruno/src/components/picker/base/brn_picker_title.dart'; import 'package:bruno/src/components/picker/base/brn_picker_title_config.dart'; @@ -18,10 +16,10 @@ typedef BrnMultiDataPickerCreateWidgetCallback = Widget Function( bool isSelect, int column, int row, List selectedItems); /// 创建一级数据widget列表 -typedef List CreateWidgetList(); +typedef CreateWidgetList = List Function(); /// 确定筛选内容事件回调 -typedef void ConfirmButtonClick(List selectedIndexList); +typedef ConfirmButtonClick = void Function(List selectedIndexList); /// 数据适配 Delegate abstract class BrnMultiDataPickerDelegate { @@ -120,19 +118,18 @@ class BrnMultiDataPicker extends StatefulWidget { this.themeData, this.sync = true}) { this.themeData ??= BrnPickerConfig(); - this.themeData = this.themeData!.merge(BrnPickerConfig( - cancelTextStyle: BrnTextStyle.withStyle(cancelTextStyle), - confirmTextStyle: BrnTextStyle.withStyle(confirmTextStyle), - titleTextStyle: BrnTextStyle.withStyle(titleTextStyle), - itemTextStyle: BrnTextStyle(color: textColor, fontSize: textFontSize), - itemTextSelectedStyle: - BrnTextStyle(color: textSelectedColor, fontSize: textFontSize), - )); - this.themeData = BrnThemeConfigurator.instance .getConfig(configId: this.themeData!.configId) .pickerConfig .merge(this.themeData); + this.themeData = this.themeData!.merge(BrnPickerConfig( + cancelTextStyle: BrnTextStyle.withStyle(cancelTextStyle), + confirmTextStyle: BrnTextStyle.withStyle(confirmTextStyle), + titleTextStyle: BrnTextStyle.withStyle(titleTextStyle), + itemTextStyle: BrnTextStyle(color: textColor, fontSize: textFontSize), + itemTextSelectedStyle: + BrnTextStyle(color: textSelectedColor, fontSize: textFontSize), + )); } @override @@ -198,8 +195,9 @@ class _BrnMultiDataPickerState extends State { }, onConfirm: () { Navigator.of(context).pop(_selectedIndexList); - if (widget.confirmClick != null) + if (widget.confirmClick != null) { widget.confirmClick!(_selectedIndexList); + } }, ); } @@ -211,17 +209,14 @@ class _BrnMultiDataPickerState extends State { color: widget.themeData?.backgroundColor, child: Row( mainAxisSize: MainAxisSize.max, - children: widget.pickerTitles != null - ? _pickersWithTitle() - : _pickers())); + children: widget.pickerTitles != null ? _pickersWithTitle() : _pickers())); } List _pickersWithTitle() { List pickersWithTitle = []; for (int i = 0; i < widget.delegate.numberOfComponent(); i++) { int initRow = widget.delegate.initSelectedRowForComponent(i); - FixedExtentScrollController controller = - FixedExtentScrollController(initialItem: initRow); + FixedExtentScrollController controller = FixedExtentScrollController(initialItem: initRow); widget.controllers.add(controller); if (i >= _selectedIndexList.length) _selectedIndexList.add(0); Widget picker = _configSinglePicker(i); @@ -237,8 +232,7 @@ class _BrnMultiDataPickerState extends State { child: Text( widget.pickerTitles == null ? '' : widget.pickerTitles![i], style: TextStyle( - fontSize: widget.pickerTitleFontSize, - color: widget.pickerTitleColor), + fontSize: widget.pickerTitleFontSize, color: widget.pickerTitleColor), ), ), ), @@ -254,8 +248,7 @@ class _BrnMultiDataPickerState extends State { List pickers = []; for (int i = 0; i < widget.delegate.numberOfComponent(); i++) { int initRow = widget.delegate.initSelectedRowForComponent(i); - FixedExtentScrollController controller = - FixedExtentScrollController(initialItem: initRow); + FixedExtentScrollController controller = FixedExtentScrollController(initialItem: initRow); widget.controllers.add(controller); if (i >= _selectedIndexList.length) _selectedIndexList.add(0); Widget picker = _configSinglePicker(i); @@ -274,27 +267,21 @@ class _BrnMultiDataPickerState extends State { createWidgetList: () { if (widget.createItemWidget != null) { List widgetList = []; - for (int i = 0; - i < widget.delegate.numberOfRowsInComponent(component); - i++) { + for (int i = 0; i < widget.delegate.numberOfRowsInComponent(component); i++) { bool isSelect = _selectedIndexList[component] == i; widgetList.add(widget.createItemWidget != null - ? widget.createItemWidget!( - isSelect, component, i, _selectedIndexList) + ? widget.createItemWidget!(isSelect, component, i, _selectedIndexList) : Container()); } return widgetList; } else { List list = []; - for (int i = 0; - i < widget.delegate.numberOfRowsInComponent(component); - i++) { + for (int i = 0; i < widget.delegate.numberOfRowsInComponent(component); i++) { list.add(Center( child: Text( widget.delegate.titleForRowInComponent(component, i), style: _selectedIndexList[component] == i - ? widget.themeData!.itemTextSelectedStyle - .generateTextStyle() + ? widget.themeData!.itemTextSelectedStyle.generateTextStyle() : widget.themeData!.itemTextStyle.generateTextStyle(), ), )); @@ -302,21 +289,15 @@ class _BrnMultiDataPickerState extends State { return list; } }, - itemExtent: widget.delegate.rowHeightForComponent(component) ?? - widget.themeData!.itemHeight, + itemExtent: widget.delegate.rowHeightForComponent(component) ?? widget.themeData!.itemHeight, changed: (int index) { widget.delegate.selectRowInComponent(component, index); _selectedIndexList[component] = index; setState(() { - for (int i = component + 1; - i < widget.delegate.numberOfComponent(); - i++) { + for (int i = component + 1; i < widget.delegate.numberOfComponent(); i++) { List list = []; - for (int j = 0; - j < widget.delegate.numberOfRowsInComponent(component); - j++) { - list.add( - widget.delegate.titleForRowInComponent(component, index)); + for (int j = 0; j < widget.delegate.numberOfRowsInComponent(component); j++) { + list.add(widget.delegate.titleForRowInComponent(component, index)); } FixedExtentScrollController controller = widget.controllers[i]; if (widget.sync) { @@ -384,7 +365,7 @@ class _MyPickerState extends State { widget.changed!(index); } }, - children: children.length > 0 + children: children.isNotEmpty ? children : [ Center(child: Text('')), @@ -398,8 +379,130 @@ class _MyPickerState extends State { ///默认的选择轮盘滚动行为,Android去除默认的水波纹动画效果 class _DefaultScrollBehavior extends ScrollBehavior { @override - Widget buildViewportChrome( - BuildContext context, Widget child, AxisDirection axisDirection) { + Widget buildViewportChrome(BuildContext context, Widget child, AxisDirection axisDirection) { return child; } } + +/// 实现了部分默认逻辑的 Delegate +class BrnDefaultMultiDataPickerDelegate implements BrnMultiDataPickerDelegate { + ///数据源 + List data; + + ///第一列选中角标,默认0 + int firstSelectedIndex; + + ///第二列选中角标,默认0 + int secondSelectedIndex; + + ///第三列选中角标,默认0 + int thirdSelectedIndex; + + int _numberOfComponent = 0; + + BrnDefaultMultiDataPickerDelegate( + {required this.data, + this.firstSelectedIndex = 0, + this.secondSelectedIndex = 0, + this.thirdSelectedIndex = 0}) { + if (data.isNotEmpty) { + _numberOfComponent = 1; + for (BrnMultiDataPickerEntity brnPickerItem in data) { + if (brnPickerItem.children.isNotEmpty) { + _numberOfComponent = 2; + + for (BrnMultiDataPickerEntity brnPickerItem1 in brnPickerItem.children) { + if (brnPickerItem1.children.isNotEmpty) { + _numberOfComponent = 3; + } + } + } + } + } + } + + @override + int initSelectedRowForComponent(int component) { + if (0 == component) { + return firstSelectedIndex; + } else if (1 == component) { + return secondSelectedIndex; + } else { + return thirdSelectedIndex; + } + } + + ///显示几列内容 + @override + int numberOfComponent() { + return _numberOfComponent; + } + + @override + int numberOfRowsInComponent(int component) { + if (data.isEmpty) { + return 0; + } + + if (0 == component) { + return data.length; + } else if (1 == component) { + List fl = data[firstSelectedIndex].children; + return fl.length; + } else { + List secondMap = data[firstSelectedIndex].children; + List thirdMap = secondMap[secondSelectedIndex].children; + return thirdMap.length; + } + } + + @override + double rowHeightForComponent(int component) { + return pickerItemHeight; + } + + @override + void selectRowInComponent(int component, int row) { + if (0 == component) { + firstSelectedIndex = row; + } else if (1 == component) { + secondSelectedIndex = row; + } else { + thirdSelectedIndex = row; + } + } + + @override + String titleForRowInComponent(int component, int index) { + if (0 == component) { + return data[index].text; + } else if (1 == component) { + BrnMultiDataPickerEntity brnPickerItem = data[firstSelectedIndex]; + List secondList = brnPickerItem.children; + return secondList[index].text; + } else { + BrnMultiDataPickerEntity brnPickerItem = data[firstSelectedIndex]; + List secondList = brnPickerItem.children; + List threeList = secondList[secondSelectedIndex].children; + return threeList[index].text; + } + } +} + +/// 适用于 BrnDefaultMultiDataPickerDelegate 的数据类 +class BrnMultiDataPickerEntity { + /// 显示内容 + final String text; + + /// 数据值 + final dynamic value; + + /// 子项 + final List children; + + BrnMultiDataPickerEntity({ + required this.text, + this.value, + this.children = const [], + }); +} diff --git a/lib/src/components/picker/brn_picker_cliprrect.dart b/lib/src/components/picker/brn_picker_cliprrect.dart index ca5ac7e3..288acaf6 100644 --- a/lib/src/components/picker/brn_picker_cliprrect.dart +++ b/lib/src/components/picker/brn_picker_cliprrect.dart @@ -1,5 +1,3 @@ -import 'package:flutter/foundation.dart'; -import 'package:flutter/rendering.dart'; import 'package:flutter/widgets.dart'; /// Picker 顶端 圆角装饰类,参考系统 [ClipRRect], diff --git a/lib/src/components/picker/brn_select_tags_with_input_picker.dart b/lib/src/components/picker/brn_select_tags_with_input_picker.dart index 23f93c8c..9988365d 100644 --- a/lib/src/components/picker/brn_select_tags_with_input_picker.dart +++ b/lib/src/components/picker/brn_select_tags_with_input_picker.dart @@ -3,7 +3,6 @@ import 'package:bruno/src/constants/brn_asset_constants.dart'; import 'package:bruno/src/theme/brn_theme_configurator.dart'; import 'package:bruno/src/utils/brn_tools.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/rendering.dart'; ///传入的泛型数据转换为值 以填充Widget typedef SelectTagWithInputValueGetter = String Function(V data); @@ -462,8 +461,8 @@ class _BrnSelectTagsWithInputPickerWidgetState break; } } - return this._selectedTags.length > 0 && - (needExpend ? _textEditingController!.text.length > 0 : true); + return this._selectedTags.isNotEmpty && + (needExpend ? _textEditingController!.text.isNotEmpty : true); } bool isShowTextInput() { diff --git a/lib/src/components/picker/brn_tags_common_picker.dart b/lib/src/components/picker/brn_tags_common_picker.dart index d6cb4a5e..9a45f503 100644 --- a/lib/src/components/picker/brn_tags_common_picker.dart +++ b/lib/src/components/picker/brn_tags_common_picker.dart @@ -36,9 +36,10 @@ class CommonTagsPicker extends StatefulWidget { this.themeData}) : super(key: key) { this.themeData ??= BrnPickerConfig(); - this.themeData = this - .themeData! - .merge(BrnThemeConfigurator.instance.getConfig().pickerConfig); + this.themeData = BrnThemeConfigurator.instance + .getConfig(configId: this.themeData!.configId) + .pickerConfig + .merge(this.themeData); } void show() { diff --git a/lib/src/components/picker/brn_tags_picker_config.dart b/lib/src/components/picker/brn_tags_picker_config.dart index 1303df3c..ab8ffa20 100644 --- a/lib/src/components/picker/brn_tags_picker_config.dart +++ b/lib/src/components/picker/brn_tags_picker_config.dart @@ -49,10 +49,7 @@ class BrnTagsPickerConfig { this.tagBackgroudColor, this.selectedTagBackgroudColor, this.chipPadding, - this.tagItemSource = const []}) { - this.tagTitleColor = - BrnThemeConfigurator.instance.getConfig().commonConfig.colorTextBase; - } + this.tagItemSource = const []}); ///tag 文字大小 double tagTitleFontSize; diff --git a/lib/src/components/picker/multi_range_picker/bean/brn_multi_column_picker_entity.dart b/lib/src/components/picker/multi_range_picker/bean/brn_multi_column_picker_entity.dart index ab22d14a..162fe8a6 100644 --- a/lib/src/components/picker/multi_range_picker/bean/brn_multi_column_picker_entity.dart +++ b/lib/src/components/picker/multi_range_picker/bean/brn_multi_column_picker_entity.dart @@ -74,7 +74,7 @@ class BrnPickerEntity { } void configDefaultValue() { - if (this.children.length > 0) { + if (this.children.isNotEmpty) { for (BrnPickerEntity entity in this.children) { if (!BrunoTools.isEmpty(defaultValue)) { List values = defaultValue!.split(','); @@ -83,12 +83,12 @@ class BrnPickerEntity { entity.configDefaultValue(); } - isSelected = isSelected || children.where((_) => _.isSelected).length > 0; + isSelected = isSelected || children.where((_) => _.isSelected).isNotEmpty; } } void configRelationship() { - if (this.children.length > 0) { + if (this.children.isNotEmpty) { for (BrnPickerEntity entity in this.children) { entity.parent = this; entity.configRelationship(); @@ -117,7 +117,7 @@ class BrnPickerEntity { } void clearChildSelection() { - if (this.children.length > 0) { + if (this.children.isNotEmpty) { for (BrnPickerEntity entity in this.children) { entity.isSelected = false; entity.clearChildSelection(); @@ -127,16 +127,16 @@ class BrnPickerEntity { List selectedLastColumnList() { List list = []; - if (this.children.length > 0) { + if (this.children.isNotEmpty) { List firstList = []; for (BrnPickerEntity firstEntity in this.children) { - if (firstEntity.children.length > 0) { + if (firstEntity.children.isNotEmpty) { List secondList = []; for (BrnPickerEntity secondEntity in firstEntity.children) { - if (secondEntity.children.length > 0) { + if (secondEntity.children.isNotEmpty) { List thirds = this.currentSelectListForEntity(secondEntity); - if (thirds.length > 0) { + if (thirds.isNotEmpty) { list.addAll(thirds); } else if (secondEntity.isSelected) { secondList.add(secondEntity); @@ -164,12 +164,12 @@ class BrnPickerEntity { List results = []; List firstColumn = this.currentSelectListForEntity(this); results.addAll(firstColumn); - if (firstColumn.length > 0) { + if (firstColumn.isNotEmpty) { for (BrnPickerEntity firstEntity in firstColumn) { List secondColumn = this.currentSelectListForEntity(firstEntity); results.addAll(secondColumn); - if (secondColumn.length > 0) { + if (secondColumn.isNotEmpty) { for (BrnPickerEntity secondEntity in secondColumn) { List thirdColumn = this.currentSelectListForEntity(secondEntity); @@ -184,7 +184,7 @@ class BrnPickerEntity { /// 返回状态为选中的子节点 List currentSelectListForEntity(BrnPickerEntity entity) { List list = []; - if (entity.children.length > 0) { + if (entity.children.isNotEmpty) { for (BrnPickerEntity entity in entity.children) { if (entity.isSelected) { list.add(entity); @@ -210,7 +210,7 @@ class BrnPickerEntity { /// 判断当前的筛选 Item 是否为当前层次中第一个被选中的 Item。 /// 用于展开筛选弹窗时显示选中效果。 int getIndexInCurrentLevel() { - if (parent == null || parent!.children.length == 0) return -1; + if (parent == null || parent!.children.isEmpty) return -1; for (BrnPickerEntity entity in parent!.children) { if (entity == this) { @@ -221,10 +221,10 @@ class BrnPickerEntity { } bool isInLastLevel() { - if (parent == null || parent!.children.length == 0) return true; + if (parent == null || parent!.children.isEmpty) return true; for (BrnPickerEntity entity in parent!.children) { - if (entity.children.length > 0) { + if (entity.children.isNotEmpty) { return false; } } diff --git a/lib/src/components/picker/multi_range_picker/brn_multi_column_list.dart b/lib/src/components/picker/multi_range_picker/brn_multi_column_list.dart index 6297610c..fd0212f9 100644 --- a/lib/src/components/picker/multi_range_picker/brn_multi_column_list.dart +++ b/lib/src/components/picker/multi_range_picker/brn_multi_column_list.dart @@ -11,7 +11,7 @@ import 'package:flutter/material.dart'; /// [listIndex] 点击位置处于第几列 /// [index] 点击位置处于当前列的位置 /// [entity] 被点击位置的数据 -typedef bool BrnOnSelectEntityInterceptor( +typedef BrnOnSelectEntityInterceptor = bool Function( int? listIndex, int index, BrnPickerEntity entity); // ignore: must_be_immutable @@ -49,7 +49,7 @@ class BrnMultiColumnListWidget extends StatefulWidget { }); currentListIndex = BrnMultiColumnPickerUtil.getCurrentColumnIndex( - items!.length > 0 ? items![0] : null); + items!.isNotEmpty ? items![0] : null); _selectedItems = items?.where((f) => f.isSelected).toList(); if (_selectedItems == null) { @@ -160,12 +160,10 @@ class _BrnMultiColumnListWidgetState extends State { /// (两列、三列时)第一列节点是否被选中取决于它的子节点是否被选中, /// 只有当它子节点被选中时才会认为第一列的节点相应被选中。 if (widget.items != null && - widget.items!.length > 0 && + widget.items!.isNotEmpty && widget.items![0].parent != null) { widget.items![0].parent?.isSelected = widget.items![0].parent!.children - .where((BrnPickerEntity f) => f.isSelected) - .length > - 0; + .where((BrnPickerEntity f) => f.isSelected).isNotEmpty; } for (BrnPickerEntity item in widget.items!) { @@ -193,9 +191,9 @@ class _BrnMultiColumnListWidgetState extends State { selectedEntity.isSelected = true; } else { ///清除【不限】类型。 - var brotherItems; + List brotherItems; if (selectedEntity.parent == null) { - brotherItems = widget.items; + brotherItems = widget.items ?? []; } else { brotherItems = selectedEntity.parent!.children; } @@ -227,9 +225,9 @@ class _BrnMultiColumnListWidgetState extends State { selectedEntity.isSelected = true; } else { ///清除【不限】类型。 - var brotherItems; + List brotherItems; if (selectedEntity.parent == null) { - brotherItems = widget.items; + brotherItems = widget.items ?? []; } else { brotherItems = selectedEntity.parent!.children; } @@ -261,9 +259,9 @@ class _BrnMultiColumnListWidgetState extends State { selectedEntity.isSelected = true; } else { ///清除【不限】类型。 - var brotherItems; + List brotherItems; if (selectedEntity.parent == null) { - brotherItems = widget.items; + brotherItems = widget.items ?? []; } else { brotherItems = selectedEntity.parent!.children; } diff --git a/lib/src/components/picker/multi_range_picker/brn_multi_column_picker.dart b/lib/src/components/picker/multi_range_picker/brn_multi_column_picker.dart index e070c441..2e0b11a6 100644 --- a/lib/src/components/picker/multi_range_picker/brn_multi_column_picker.dart +++ b/lib/src/components/picker/multi_range_picker/brn_multi_column_picker.dart @@ -16,7 +16,7 @@ import 'package:flutter/material.dart'; /// [columnIndex] 数据项所在列 /// [rowIndex] 数据项所在列中的位置 /// [entity] 被点击的数据项 -typedef void BrnOnEntityTap( +typedef BrnOnEntityTap = void Function( int columnIndex, int rowIndex, BrnPickerEntity entity); /// 单个数据项被点击的回调, @@ -24,7 +24,7 @@ typedef void BrnOnEntityTap( /// [firstIndex] 第一列被选中数据的位置 /// [secondIndex] 第二列被选中数据的位置 /// [thirdIndex] 第三列被选中数据的位置 -typedef void BrnOnPickerConfirm(Map> results, +typedef BrnOnPickerConfirm = void Function(Map> results, int? firstIndex, int? secondIndex, int? thirdIndex); /// 从屏幕下方弹起的多级筛选选择器 @@ -455,7 +455,7 @@ class _BrnSelectionGroupViewState extends State { int _getInitialSelectIndex(List? levelList) { int index = -1; - if (levelList == null || levelList.length == 0) { + if (levelList == null || levelList.isEmpty) { return index; } diff --git a/lib/src/components/picker/multi_range_picker/brn_multi_column_picker_util.dart b/lib/src/components/picker/multi_range_picker/brn_multi_column_picker_util.dart index 27017e2e..14fb5ff0 100644 --- a/lib/src/components/picker/multi_range_picker/brn_multi_column_picker_util.dart +++ b/lib/src/components/picker/multi_range_picker/brn_multi_column_picker_util.dart @@ -1,5 +1,3 @@ - - import 'package:bruno/src/components/picker/multi_range_picker/bean/brn_multi_column_picker_entity.dart'; /// BrnMultiColumnPicker相关工具类 @@ -12,13 +10,13 @@ class BrnMultiColumnPickerUtil { rootEntity = rootEntity?.parent!; } - if (rootEntity != null && rootEntity.children.length > 0) { + if (rootEntity != null && rootEntity.children.isNotEmpty) { count = count > 1 ? count : 1; for (BrnPickerEntity firstLevelEntity in rootEntity.children) { - if (firstLevelEntity.children.length > 0) { + if (firstLevelEntity.children.isNotEmpty) { count = count > 2 ? count : 2; for (BrnPickerEntity secondLevelEntity in firstLevelEntity.children) { - if (secondLevelEntity.children.length > 0) { + if (secondLevelEntity.children.isNotEmpty) { count = 3; break; } diff --git a/lib/src/components/picker/multi_range_picker/btn_multi_column_picker_item.dart b/lib/src/components/picker/multi_range_picker/btn_multi_column_picker_item.dart index 521a3652..47821ad8 100644 --- a/lib/src/components/picker/multi_range_picker/btn_multi_column_picker_item.dart +++ b/lib/src/components/picker/multi_range_picker/btn_multi_column_picker_item.dart @@ -1,13 +1,9 @@ - - import 'package:bruno/src/components/picker/multi_range_picker/bean/brn_multi_column_picker_entity.dart'; import 'package:bruno/src/components/picker/multi_range_picker/brn_multi_column_picker_util.dart'; import 'package:bruno/src/constants/brn_asset_constants.dart'; import 'package:bruno/src/utils/brn_tools.dart'; import 'package:flutter/material.dart'; -typedef void ItemSelectFunction(BrnPickerEntity entity); - class BrnMultiRangePickerCommonItem extends StatelessWidget { final BrnPickerEntity item; final Color normalColor; @@ -19,7 +15,7 @@ class BrnMultiRangePickerCommonItem extends StatelessWidget { final bool isMoreSelectionListType; - final ItemSelectFunction? itemSelectFunction; + final ValueChanged? itemSelectFunction; BrnMultiRangePickerCommonItem({ required this.item, @@ -35,8 +31,8 @@ class BrnMultiRangePickerCommonItem extends StatelessWidget { @override Widget build(BuildContext context) { - var checkbox; - if (!item.isUnLimit() && (item.children.length == 0)) { + Container checkbox; + if (!item.isUnLimit() && (item.children.isEmpty)) { if (item.isInLastLevel() && _hasCheckBoxBrother(item)) { checkbox = Container( padding: EdgeInsets.only(left: 6), diff --git a/lib/src/components/picker/time_picker/brn_date_picker_constants.dart b/lib/src/components/picker/time_picker/brn_date_picker_constants.dart index f8c04c82..cdb7f280 100755 --- a/lib/src/components/picker/time_picker/brn_date_picker_constants.dart +++ b/lib/src/components/picker/time_picker/brn_date_picker_constants.dart @@ -1,15 +1,15 @@ /// Selected value of DatePicker. -typedef DateValueCallback(DateTime dateTime, List selectedIndex); +typedef DateValueCallback = Function(DateTime dateTime, List selectedIndex); -typedef DateRangeValueCallback(DateTime startDateTime, DateTime endDateTime, +typedef DateRangeValueCallback = Function(DateTime startDateTime, DateTime endDateTime, List startSelectedIndex, List endSelectedIndex); -typedef DateRangeSideValueCallback( +typedef DateRangeSideValueCallback = Function( DateTime selectDateTime, List selectedIndex); /// Pressed cancel callback. -typedef DateVoidCallback(); +typedef DateVoidCallback = Function(); /// Default value of minimum datetime. const String datePickerMinDatetime = "1900-01-01 00:00:00"; diff --git a/lib/src/components/picker/time_picker/brn_date_time_formatter.dart b/lib/src/components/picker/time_picker/brn_date_time_formatter.dart index 0994b820..e89c1f16 100755 --- a/lib/src/components/picker/time_picker/brn_date_time_formatter.dart +++ b/lib/src/components/picker/time_picker/brn_date_time_formatter.dart @@ -29,7 +29,7 @@ class DateTimeFormatter { /// Get default value of date format. static String generateDateFormat( String? dateFormat, BrnDateTimePickerMode pickerMode) { - if (dateFormat != null && dateFormat.length > 0) { + if (dateFormat != null && dateFormat.isNotEmpty) { return dateFormat; } switch (pickerMode) { @@ -44,7 +44,7 @@ class DateTimeFormatter { static String generateDateRangePickerFormat( String? dateFormat, BrnDateTimeRangePickerMode pickerMode) { - if (dateFormat != null && dateFormat.length > 0) { + if (dateFormat != null && dateFormat.isNotEmpty) { return dateFormat; } switch (pickerMode) { @@ -68,7 +68,7 @@ class DateTimeFormatter { /// Split date format to array. static List splitDateFormat(String? dateFormat, {BrnDateTimePickerMode? mode}) { - if (dateFormat == null || dateFormat.length == 0) { + if (dateFormat == null || dateFormat.isEmpty) { return []; } List result = dateFormat.split(RegExp(DATE_FORMAT_SEPARATOR)); @@ -107,7 +107,7 @@ class DateTimeFormatter { /// Format datetime string static String formatDateTime( int value, String format, DateTimePickerLocale locale) { - if (format.length == 0) { + if (format.isEmpty) { return value.toString(); } @@ -148,7 +148,7 @@ class DateTimeFormatter { /// Format day display static String formatDate( DateTime dateTime, String format, DateTimePickerLocale locale) { - if (format.length == 0) { + if (format.isEmpty) { return dateTime.toString(); } diff --git a/lib/src/components/picker/time_picker/date_picker/brn_datetime_widget.dart b/lib/src/components/picker/time_picker/date_picker/brn_datetime_widget.dart index 18a6e077..6f842698 100755 --- a/lib/src/components/picker/time_picker/date_picker/brn_datetime_widget.dart +++ b/lib/src/components/picker/time_picker/date_picker/brn_datetime_widget.dart @@ -216,19 +216,19 @@ class _BrnDateTimeWidgetState extends State { /// 如果传入的时间格式不包含 月、天、小时、分钟、秒。则相对应的时间置为 1,1,0,0,0; DateTime dateTime = DateTime( _currYear, - (formatArr.where((format) => format.contains('M')).toList()).length > 0 + (formatArr.where((format) => format.contains('M')).toList()).isNotEmpty ? _currMonth : 1, - (formatArr.where((format) => format.contains('d')).toList()).length > 0 + (formatArr.where((format) => format.contains('d')).toList()).isNotEmpty ? _currDay : 1, - (formatArr.where((format) => format.contains('H')).toList()).length > 0 + (formatArr.where((format) => format.contains('H')).toList()).isNotEmpty ? _currHour : 0, - (formatArr.where((format) => format.contains('m')).toList()).length > 0 + (formatArr.where((format) => format.contains('m')).toList()).isNotEmpty ? _currMinute : 0, - (formatArr.where((format) => format.contains('s')).toList()).length > 0 + (formatArr.where((format) => format.contains('s')).toList()).isNotEmpty ? _currSecond : 0, ); diff --git a/lib/src/components/picker/time_picker/date_range_picker/brn_date_range_side_widget.dart b/lib/src/components/picker/time_picker/date_range_picker/brn_date_range_side_widget.dart index fb3a4afb..b975afac 100755 --- a/lib/src/components/picker/time_picker/date_range_picker/brn_date_range_side_widget.dart +++ b/lib/src/components/picker/time_picker/date_range_picker/brn_date_range_side_widget.dart @@ -212,7 +212,7 @@ class _DatePickerWidgetState extends State { required String format, required ValueChanged valueChanged, }) { - var globalKey; + GlobalKey? globalKey; if (_scrolledNotDay && format.contains("d")) { globalKey = GlobalKey(); _scrolledNotDay = false; diff --git a/lib/src/components/picker/time_picker/date_range_picker/brn_date_range_widget.dart b/lib/src/components/picker/time_picker/date_range_picker/brn_date_range_widget.dart index e5f311b1..ff43ddb6 100755 --- a/lib/src/components/picker/time_picker/date_range_picker/brn_date_range_widget.dart +++ b/lib/src/components/picker/time_picker/date_range_picker/brn_date_range_widget.dart @@ -191,8 +191,8 @@ class _DatePickerWidgetState extends State { /// render the picker widget of year、month and day Widget _renderDatePickerWidget() { /// 用于强制刷新 Widget - var firstGlobalKey; - var secondGlobalKey; + GlobalKey? firstGlobalKey; + GlobalKey? secondGlobalKey; if (_isFirstScroll) { secondGlobalKey = GlobalKey(); diff --git a/lib/src/components/picker/time_picker/date_range_picker/brn_time_range_side_widget.dart b/lib/src/components/picker/time_picker/date_range_picker/brn_time_range_side_widget.dart index d1841e8e..1a0573e0 100755 --- a/lib/src/components/picker/time_picker/date_range_picker/brn_time_range_side_widget.dart +++ b/lib/src/components/picker/time_picker/date_range_picker/brn_time_range_side_widget.dart @@ -232,7 +232,7 @@ class _TimePickerWidgetState extends State { required String format, required ValueChanged valueChanged, }) { - var globalKey; + GlobalKey? globalKey; if (_scrolledNotMinute && format.contains("m")) { globalKey = GlobalKey(); _scrolledNotMinute = false; diff --git a/lib/src/components/picker/time_picker/date_range_picker/brn_time_range_widget.dart b/lib/src/components/picker/time_picker/date_range_picker/brn_time_range_widget.dart index ef48138d..07fe2d61 100755 --- a/lib/src/components/picker/time_picker/date_range_picker/brn_time_range_widget.dart +++ b/lib/src/components/picker/time_picker/date_range_picker/brn_time_range_widget.dart @@ -27,7 +27,7 @@ class BrnTimeRangeWidget extends StatefulWidget { final DateTime? initialEndDateTime; /// 是否限制 Picker 选择的时间范围(开始时间≤结束时间) - final isLimitTimeRange; + final bool isLimitTimeRange; /// 时间格式 final String? dateFormat; @@ -212,8 +212,8 @@ class _TimePickerWidgetState extends State { /// render the picker widget of year、month and day Widget _renderDatePickerWidget() { /// 用于强制刷新 Widget - var firstGlobalKey; - var secondGlobalKey; + GlobalKey? firstGlobalKey; + GlobalKey? secondGlobalKey; if (widget._isFirstScroll) { secondGlobalKey = GlobalKey(); @@ -237,7 +237,7 @@ class _TimePickerWidgetState extends State { maxDateTime: _maxTime, initialStartDateTime: _startSelectedDateTime, minuteDivider: _minuteDivider, - onInitSelectChange: (widget.isLimitTimeRange ?? true) + onInitSelectChange: (widget.isLimitTimeRange) ? (DateTime selectedDateTime, List selected) { _startSelectedDateTime = selectedDateTime; _startSelectedIndex = selected; @@ -260,17 +260,17 @@ class _TimePickerWidgetState extends State { child: BrnTimeRangeSideWidget( key: secondGlobalKey, dateFormat: widget.dateFormat, - minDateTime: (widget.isLimitTimeRange ?? true) + minDateTime: (widget.isLimitTimeRange) ? _startSelectedDateTime : _minTime, maxDateTime: _maxTime, - initialStartDateTime: (widget.isLimitTimeRange ?? true) + initialStartDateTime: (widget.isLimitTimeRange) ? _endSelectedDateTime.compareTo(_startSelectedDateTime) > 0 ? _endSelectedDateTime : _startSelectedDateTime : _endSelectedDateTime, minuteDivider: _minuteDivider, - onInitSelectChange: (widget.isLimitTimeRange ?? true) + onInitSelectChange: (widget.isLimitTimeRange) ? (DateTime selectedDateTime, List selected) { _endSelectedDateTime = selectedDateTime; _endSelectedIndex = selected; diff --git a/lib/src/components/popup/brn_measure_size.dart b/lib/src/components/popup/brn_measure_size.dart index d2e08eaf..199f3e89 100644 --- a/lib/src/components/popup/brn_measure_size.dart +++ b/lib/src/components/popup/brn_measure_size.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; -typedef void OnWidgetSizeChange(Size size); +typedef OnWidgetSizeChange = void Function(Size size); /// 描述: 计算 Widget 宽高的工具类。 class MeasureSizeRenderObject extends RenderProxyBox { diff --git a/lib/src/components/radio/brn_checkbox.dart b/lib/src/components/radio/brn_checkbox.dart index ae1f216c..98a1e597 100644 --- a/lib/src/components/radio/brn_checkbox.dart +++ b/lib/src/components/radio/brn_checkbox.dart @@ -36,6 +36,10 @@ class BrnCheckbox extends StatefulWidget { /// 默认值MainAxisAlignment.start final MainAxisAlignment mainAxisAlignment; + /// 控件和选择按钮在row布局里面的crossAxisAlignment + /// 默认值CrossAxisAlignment.center + final CrossAxisAlignment crossAxisAlignment; + /// 控件和选择按钮在row布局里面的mainAxisSize /// 默认值MainAxisSize.min final MainAxisSize mainAxisSize; @@ -53,6 +57,7 @@ class BrnCheckbox extends StatefulWidget { this.child, this.childOnRight = true, this.mainAxisAlignment = MainAxisAlignment.start, + this.crossAxisAlignment = CrossAxisAlignment.center, this.mainAxisSize = MainAxisSize.min, this.behavior = HitTestBehavior.translucent}); @@ -80,6 +85,7 @@ class BrnCheckboxState extends State { iconPadding: widget.iconPadding, childOnRight: widget.childOnRight, mainAxisAlignment: widget.mainAxisAlignment, + crossAxisAlignment: widget.crossAxisAlignment, mainAxisSize: widget.mainAxisSize, selectedImage: BrunoTools.getAssetImageWithBandColor( BrnAsset.iconRadioMultiSelected), diff --git a/lib/src/components/radio/brn_radio_button.dart b/lib/src/components/radio/brn_radio_button.dart index 44c93e20..071f229b 100644 --- a/lib/src/components/radio/brn_radio_button.dart +++ b/lib/src/components/radio/brn_radio_button.dart @@ -36,6 +36,10 @@ class BrnRadioButton extends StatelessWidget { /// 默认值MainAxisAlignment.start final MainAxisAlignment mainAxisAlignment; + /// 控件和选择按钮在row布局里面的crossAxisAlignment + /// 默认值CrossAxisAlignment.center + final CrossAxisAlignment crossAxisAlignment; + /// 控件和选择按钮在row布局里面的mainAxisSize /// 默认值MainAxisSize.min final MainAxisSize mainAxisSize; @@ -53,6 +57,7 @@ class BrnRadioButton extends StatelessWidget { this.child, this.childOnRight = true, this.mainAxisAlignment = MainAxisAlignment.start, + this.crossAxisAlignment = CrossAxisAlignment.center, this.mainAxisSize = MainAxisSize.min, this.behavior = HitTestBehavior.translucent}); @@ -65,6 +70,7 @@ class BrnRadioButton extends StatelessWidget { iconPadding: iconPadding, childOnRight: childOnRight, mainAxisAlignment: mainAxisAlignment, + crossAxisAlignment: crossAxisAlignment, mainAxisSize: mainAxisSize, selectedImage: BrunoTools.getAssetImageWithBandColor( BrnAsset.iconRadioSingleSelected), diff --git a/lib/src/components/radio/brn_radio_core.dart b/lib/src/components/radio/brn_radio_core.dart index 2d0af1e0..c4545f90 100644 --- a/lib/src/components/radio/brn_radio_core.dart +++ b/lib/src/components/radio/brn_radio_core.dart @@ -35,6 +35,10 @@ class BrnRadioCore extends StatefulWidget { /// 默认值MainAxisAlignment.start final MainAxisAlignment mainAxisAlignment; + /// 控件和选择按钮在row布局里面的crossAxisAlignment + /// 默认值CrossAxisAlignment.center + final CrossAxisAlignment crossAxisAlignment; + /// 控件和选择按钮在row布局里面的mainAxisSize /// 默认值MainAxisSize.min final MainAxisSize mainAxisSize; @@ -61,6 +65,7 @@ class BrnRadioCore extends StatefulWidget { this.child, this.childOnRight = true, this.mainAxisAlignment = MainAxisAlignment.start, + this.crossAxisAlignment = CrossAxisAlignment.center, this.mainAxisSize = MainAxisSize.min, this.selectedImage, this.unselectedImage, @@ -129,6 +134,7 @@ class _BrnRadioCoreState extends State { radioWidget = Row( mainAxisSize: widget.mainAxisSize, mainAxisAlignment: widget.mainAxisAlignment, + crossAxisAlignment: widget.crossAxisAlignment, children: list, ); } diff --git a/lib/src/components/scroll_anchor/brn_scroll_anchor_tab.dart b/lib/src/components/scroll_anchor/brn_scroll_anchor_tab.dart index 9a096a21..90bf83e3 100644 --- a/lib/src/components/scroll_anchor/brn_scroll_anchor_tab.dart +++ b/lib/src/components/scroll_anchor/brn_scroll_anchor_tab.dart @@ -1,23 +1,18 @@ - - -import 'dart:async'; - +import 'package:bruno/src/components/popup/brn_measure_size.dart'; import 'package:bruno/src/components/tabbar/normal/brn_tab_bar.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; /// 构建指定索引的Widget -typedef AnchorTabWidgetIndexedBuilder = Widget Function( - BuildContext context, int index); +typedef AnchorTabWidgetIndexedBuilder = Widget Function(BuildContext context, int index); /// 构建指定索引的Tab -typedef AnchorTabIndexedBuilder = BadgeTab Function( - BuildContext context, int index); +typedef AnchorTabIndexedBuilder = BadgeTab Function(BuildContext context, int index); class BrnAnchorTab extends StatefulWidget { // TabBar的样式 final BrnAnchorTabBarStyle tabBarStyle; - final AnchorTabWidgetIndexedBuilder widgetIndexedBuilder; + final AnchorTabWidgetIndexedBuilder? widgetIndexedBuilder; final AnchorTabIndexedBuilder tabIndexedBuilder; final Widget? tabDivider; @@ -32,8 +27,7 @@ class BrnAnchorTab extends StatefulWidget { this.tabBarStyle = const BrnAnchorTabBarStyle()}); @override - _BrnScrollAnchorTabWidgetState createState() => - _BrnScrollAnchorTabWidgetState(); + _BrnScrollAnchorTabWidgetState createState() => _BrnScrollAnchorTabWidgetState(); } class _BrnScrollAnchorTabWidgetState extends State @@ -41,9 +35,6 @@ class _BrnScrollAnchorTabWidgetState extends State //用于控制 滑动 late ScrollController _scrollController; - //用于 滑动 和 tab 之间的通信 - late StreamController _streamController; - //用于控制tab late TabController _tabController; @@ -53,18 +44,12 @@ class _BrnScrollAnchorTabWidgetState extends State //当前选中的索引 int currentIndex = 0; - //滑动组件的元素、 - late List _bodyWidgetList; - //滑动组件的元素的key late List _bodyKeyList; //每个元素在滑动组件中的位置 late List _cardOffsetList; - //tab - late List _tabList; - //是否点击滑动 bool tab = false; @@ -73,32 +58,48 @@ class _BrnScrollAnchorTabWidgetState extends State @override void initState() { - _streamController = StreamController(); + super.initState(); _scrollController = ScrollController(); _key = GlobalKey(); _cardOffsetList = List.filled(widget.itemCount, -1.0); - _bodyWidgetList = []; _bodyKeyList = []; - _tabList = []; - + currentIndex = 0; _tabController = TabController(length: widget.itemCount, vsync: this); fillKeyList(); - fillList(); - fillTab(); - WidgetsBinding.instance!.addPostFrameCallback((da) { + WidgetsBinding.instance?.addPostFrameCallback((da) { fillOffset(); _scrollController.addListener(() { - updateOffset(); + _updateOffset(); currentIndex = createIndex(_scrollController.offset); //防止再次 发送消息 - if (!tab) _streamController.add(currentIndex); + if (!tab) { + _tabController.index = currentIndex; + } }); }); + } - super.initState(); + @override + void didUpdateWidget(BrnAnchorTab oldWidget) { + super.didUpdateWidget(oldWidget); + _cardOffsetList = List.filled(widget.itemCount, -1.0); + int sub = widget.itemCount - oldWidget.itemCount; + if (sub < 0) { + _bodyKeyList = _bodyKeyList.sublist(0, widget.itemCount); + } else if (sub > 0) { + for (int i = 0; i < sub; i++) { + _bodyKeyList.add(GlobalKey()); + } + } + if (sub != 0) { + _tabController = TabController(length: widget.itemCount, vsync: this); + } + WidgetsBinding.instance?.addPostFrameCallback((da) { + fillOffset(); + }); } @override @@ -106,48 +107,36 @@ class _BrnScrollAnchorTabWidgetState extends State return Column( mainAxisSize: MainAxisSize.min, children: [ - StreamBuilder( - initialData: currentIndex, - stream: _streamController.stream, - builder: (context, snap) { - _tabController.index = currentIndex; - return BrnTabBar( - indicatorColor: widget.tabBarStyle.indicatorColor, - indicatorWeight: widget.tabBarStyle.indicatorWeight, - indicatorPadding: widget.tabBarStyle.indicatorPadding, - labelColor: widget.tabBarStyle.labelColor, - labelStyle: widget.tabBarStyle.labelStyle, - labelPadding: widget.tabBarStyle.labelPadding ?? EdgeInsets.zero, - unselectedLabelColor: widget.tabBarStyle.unselectedLabelColor, - unselectedLabelStyle: widget.tabBarStyle.unselectedLabelStyle, - dragStartBehavior: widget.tabBarStyle.dragStartBehavior, - controller: _tabController, - tabs: _tabList, - onTap: (state, index) { - state.refreshBadgeState(index); - currentIndex = index; - tab = true; - _scrollController - .animateTo(_cardOffsetList[index], - duration: Duration(milliseconds: 100), - curve: Curves.linear) - .whenComplete(() { - tab = false; - }); - }, - ); + BrnTabBar( + indicatorColor: widget.tabBarStyle.indicatorColor, + indicatorWeight: widget.tabBarStyle.indicatorWeight, + indicatorPadding: widget.tabBarStyle.indicatorPadding, + labelColor: widget.tabBarStyle.labelColor, + labelStyle: widget.tabBarStyle.labelStyle, + labelPadding: widget.tabBarStyle.labelPadding ?? EdgeInsets.zero, + unselectedLabelColor: widget.tabBarStyle.unselectedLabelColor, + unselectedLabelStyle: widget.tabBarStyle.unselectedLabelStyle, + dragStartBehavior: widget.tabBarStyle.dragStartBehavior, + controller: _tabController, + tabs: _fillTab(), + onTap: (state, index) { + state.refreshBadgeState(index); + currentIndex = index; + tab = true; + _scrollController + .animateTo(_cardOffsetList[index], + duration: Duration(milliseconds: 100), curve: Curves.linear) + .whenComplete(() { + tab = false; + }); }, ), - widget.tabDivider ?? - Container( - height: 0, - width: 0, - ), + widget.tabDivider ?? SizedBox.shrink(), Expanded( child: SingleChildScrollView( child: Column( mainAxisSize: MainAxisSize.min, - children: _bodyWidgetList, + children: _fillList(), ), key: _key, controller: _scrollController, @@ -157,14 +146,22 @@ class _BrnScrollAnchorTabWidgetState extends State ); } - void fillList() { - for (int i = 0, n = widget.itemCount; i < n; i++) { - _bodyWidgetList.add( - Container( - key: _bodyKeyList[i], - child: widget.widgetIndexedBuilder(context, i)), - ); + List _fillList() { + List tmpWidget = []; + if (widget.widgetIndexedBuilder != null) { + for (int i = 0, n = widget.itemCount; i < n; i++) { + Widget itemWidget = + Container(key: _bodyKeyList[i], child: widget.widgetIndexedBuilder!(context, i)); + itemWidget = MeasureSize( + onChange: (size) { + _updateOffset(); + }, + child: itemWidget, + ); + tmpWidget.add(itemWidget); + } } + return tmpWidget; } void fillKeyList() { @@ -175,37 +172,34 @@ class _BrnScrollAnchorTabWidgetState extends State void fillOffset() { Offset globalToLocal = - (_key.currentContext!.findRenderObject() as RenderBox) - .localToGlobal(Offset.zero); + (_key.currentContext!.findRenderObject() as RenderBox).localToGlobal(Offset.zero); listDy = globalToLocal.dy; for (int i = 0, n = widget.itemCount; i < n; i++) { - if (_cardOffsetList[i] == -1.0) if (_bodyKeyList[i].currentContext != - null) { - double cardOffset = - (_bodyKeyList[i].currentContext!.findRenderObject() as RenderBox) - .localToGlobal(Offset.zero) //相对于原点 控件的位置 - .dy; //y点坐标 + if (_cardOffsetList[i] == -1.0 && _bodyKeyList[i].currentContext != null) { + double cardOffset = (_bodyKeyList[i].currentContext!.findRenderObject() as RenderBox) + .localToGlobal(Offset.zero) //相对于原点 控件的位置 + .dy; //y点坐标 _cardOffsetList[i] = cardOffset + _scrollController.offset - listDy; } } } - void fillTab() { + List _fillTab() { + List tmp = []; for (int i = 0, n = widget.itemCount; i < n; i++) { - _tabList.add(widget.tabIndexedBuilder(context, i)); + tmp.add(widget.tabIndexedBuilder(context, i)); } + return tmp; } - void updateOffset() { + void _updateOffset() { for (int i = 0, n = widget.itemCount; i < n; i++) { - if (_cardOffsetList[i] == -1.0) if (_bodyKeyList[i].currentContext != - null) { - double cardOffset = - (_bodyKeyList[i].currentContext!.findRenderObject() as RenderBox) - .localToGlobal(Offset.zero) //相对于原点 控件的位置 - .dy; //y点坐标 + if (_bodyKeyList[i].currentContext != null) { + double cardOffset = (_bodyKeyList[i].currentContext!.findRenderObject() as RenderBox) + .localToGlobal(Offset.zero) //相对于原点 控件的位置 + .dy; //y点坐标 _cardOffsetList[i] = cardOffset + _scrollController.offset - listDy; } @@ -214,8 +208,8 @@ class _BrnScrollAnchorTabWidgetState extends State //根据偏移量 确定tab索引 int createIndex(double offset) { - int index = 0; - for (int i = 0, n = widget.itemCount; i < n; i++) { + int index = widget.itemCount - 1;; + for (int i = 0; i < widget.itemCount - 1; i++) { if (offset >= _cardOffsetList[i] && (offset <= _cardOffsetList[i + 1])) { return i; } @@ -227,7 +221,6 @@ class _BrnScrollAnchorTabWidgetState extends State void dispose() { super.dispose(); _tabController.dispose(); - _streamController.close(); _scrollController.dispose(); } } diff --git a/lib/src/components/selectcity/brn_az_listview.dart b/lib/src/components/selectcity/brn_az_listview.dart index 5243f172..c3d306a9 100644 --- a/lib/src/components/selectcity/brn_az_listview.dart +++ b/lib/src/components/selectcity/brn_az_listview.dart @@ -5,16 +5,16 @@ import 'package:flutter/material.dart'; /// Called to build children for the listView. /// 列表的Item -typedef Widget ItemWidgetBuilder(BuildContext context, ISuspensionBean model); +typedef ItemWidgetBuilder = Widget Function(BuildContext context, ISuspensionBean model); /// Called to build IndexBar. /// 右侧索引区域 -typedef Widget IndexBarBuilder( +typedef IndexBarBuilder = Widget Function( BuildContext context, List tags, IndexBarTouchCallback onTouch); /// Called to build index hint. /// 右侧索引项滑动或点击 页面显示的Widget -typedef Widget IndexHintBuilder(BuildContext context, String hint); +typedef IndexHintBuilder = Widget Function(BuildContext context, String hint); /// _Header. class _Header extends ISuspensionBean { diff --git a/lib/src/components/selectcity/brn_index_bar.dart b/lib/src/components/selectcity/brn_index_bar.dart index 3db2109e..e71d23ad 100644 --- a/lib/src/components/selectcity/brn_index_bar.dart +++ b/lib/src/components/selectcity/brn_index_bar.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; /// IndexBar touch callback IndexModel. -typedef void IndexBarTouchCallback(IndexBarDetails model); +typedef IndexBarTouchCallback = void Function(IndexBarDetails model); /// IndexModel. class IndexBarDetails { diff --git a/lib/src/components/selectcity/brn_single_select_city_page.dart b/lib/src/components/selectcity/brn_single_select_city_page.dart index b8b7c961..7d5d54a3 100644 --- a/lib/src/components/selectcity/brn_single_select_city_page.dart +++ b/lib/src/components/selectcity/brn_single_select_city_page.dart @@ -342,7 +342,7 @@ class _BrnSingleSelectCityPageState extends State { ///城市搜索结果页 Widget _buildSearchResultList(String searchText) { List cList = _searchCityList(searchText); - return (cList.length == 0) + return (cList.isEmpty) ? _noDataWidget() : Expanded( flex: 1, diff --git a/lib/src/components/selectcity/brn_suspension_view.dart b/lib/src/components/selectcity/brn_suspension_view.dart index 34f0bcbc..b7c8f82c 100644 --- a/lib/src/components/selectcity/brn_suspension_view.dart +++ b/lib/src/components/selectcity/brn_suspension_view.dart @@ -2,7 +2,7 @@ import 'package:bruno/src/components/selectcity/brn_az_common.dart'; import 'package:flutter/material.dart'; /// on all sus section callback(map: Used to scroll the list to the specified tag location). -typedef void OnSusSectionCallBack(Map map); +typedef SusSectionTapCallback = void Function(Map map); ///Suspension Widget.Currently only supports fixed height items! class SuspensionView extends StatefulWidget { @@ -28,7 +28,7 @@ class SuspensionView extends StatefulWidget { final ValueChanged? onSusTagChanged; /// on sus section callback. - final OnSusSectionCallBack? onSusSectionInited; + final SusSectionTapCallback? onSusSectionInited; final AzListViewHeader? header; diff --git a/lib/src/components/selection/bean/brn_selection_common_entity.dart b/lib/src/components/selection/bean/brn_selection_common_entity.dart index 1bc70af5..1b71d5ac 100644 --- a/lib/src/components/selection/bean/brn_selection_common_entity.dart +++ b/lib/src/components/selection/bean/brn_selection_common_entity.dart @@ -204,7 +204,7 @@ class BrnSelectionEntity { } void configRelationship() { - if (children.length > 0) { + if (children.isNotEmpty) { for (BrnSelectionEntity entity in children) { entity.parent = this; } @@ -215,7 +215,7 @@ class BrnSelectionEntity { } void configDefaultValue() { - if (children.length > 0) { + if (children.isNotEmpty) { for (BrnSelectionEntity entity in children) { if (!BrunoTools.isEmpty(defaultValue)) { List values = defaultValue!.split(','); @@ -224,7 +224,7 @@ class BrnSelectionEntity { } /// 当 default 不在普通 Item 类型中时,尝试填充 同级别 Range Item. - if (children.where((_) => _.isSelected).toList().length == 0) { + if (children.where((_) => _.isSelected).toList().isEmpty) { List rangeItems = this.children.where((_) { return (_.filterType == BrnSelectionFilterType.range || _.filterType == BrnSelectionFilterType.dateRange || @@ -250,10 +250,10 @@ class BrnSelectionEntity { entity.configDefaultValue(); } if (hasCheckBoxBrother()) { - isSelected = children.where((_) => _.isSelected).length > 0; + isSelected = children.where((_) => _.isSelected).isNotEmpty; } else { isSelected = - isSelected || children.where((_) => _.isSelected).length > 0; + isSelected || children.where((_) => _.isSelected).isNotEmpty; } } } @@ -295,7 +295,7 @@ class BrnSelectionEntity { } void clearChildSelection() { - if (children.length > 0) { + if (children.isNotEmpty) { for (BrnSelectionEntity entity in children) { entity.isSelected = false; if (entity.filterType == BrnSelectionFilterType.date) { @@ -313,16 +313,16 @@ class BrnSelectionEntity { List selectedLastColumnList() { List list = []; - if (this.children.length > 0) { + if (this.children.isNotEmpty) { List firstList = []; for (BrnSelectionEntity firstEntity in this.children) { - if (firstEntity.children.length > 0) { + if (firstEntity.children.isNotEmpty) { List secondList = []; for (BrnSelectionEntity secondEntity in firstEntity.children) { - if (secondEntity.children.length > 0) { + if (secondEntity.children.isNotEmpty) { List thirds = BrnSelectionUtil.currentSelectListForEntity(secondEntity); - if (thirds.length > 0) { + if (thirds.isNotEmpty) { list.addAll(thirds); } else if (secondEntity.isSelected) { secondList.add(secondEntity); @@ -368,12 +368,12 @@ class BrnSelectionEntity { List firstColumn = BrnSelectionUtil.currentSelectListForEntity(this); results.addAll(firstColumn); - if (firstColumn.length > 0) { + if (firstColumn.isNotEmpty) { for (BrnSelectionEntity firstEntity in firstColumn) { List secondColumn = BrnSelectionUtil.currentSelectListForEntity(firstEntity); results.addAll(secondColumn); - if (secondColumn.length > 0) { + if (secondColumn.isNotEmpty) { for (BrnSelectionEntity secondEntity in secondColumn) { List thirdColumn = BrnSelectionUtil.currentSelectListForEntity(secondEntity); @@ -391,12 +391,12 @@ class BrnSelectionEntity { List firstColumn = BrnSelectionUtil.currentSelectListForEntity(this); results.addAll(firstColumn); - if (firstColumn.length > 0) { + if (firstColumn.isNotEmpty) { for (BrnSelectionEntity firstEntity in firstColumn) { List secondColumn = BrnSelectionUtil.currentSelectListForEntity(firstEntity); results.addAll(secondColumn); - if (secondColumn.length > 0) { + if (secondColumn.isNotEmpty) { for (BrnSelectionEntity secondEntity in secondColumn) { List thirdColumn = BrnSelectionUtil.currentSelectListForEntity(secondEntity); @@ -442,7 +442,7 @@ class BrnSelectionEntity { /// 判断当前的筛选 Item 是否为当前层次中第一个被选中的 Item。 /// 用于展开筛选弹窗时显示选中效果。 int getIndexInCurrentLevel() { - if (parent == null || parent!.children.length == 0) return -1; + if (parent == null || parent!.children.isEmpty) return -1; for (BrnSelectionEntity entity in parent!.children) { if (entity == this) { @@ -454,10 +454,10 @@ class BrnSelectionEntity { /// 是否在筛选数据的最后一层。 如果最大层次为 3;某个筛选数据层次为 2,但其无子节点。此时认为不在最后一层。 bool isInLastLevel() { - if (parent == null || parent!.children.length == 0) return true; + if (parent == null || parent!.children.isEmpty) return true; for (BrnSelectionEntity entity in parent!.children) { - if (entity.children.length > 0) { + if (entity.children.isNotEmpty) { return false; } } @@ -521,11 +521,11 @@ class BrnSelectionEntity { /// 接口返回默认展示tag个数 int getDefaultShowCount() { - int defaultCount = 3; + int defaultShowCount = 3; if (extMap.containsKey('defaultShowCount')) { - defaultCount = extMap['defaultShowCount'] ?? 3; + defaultShowCount = extMap['defaultShowCount'] ?? defaultShowCount; } - return defaultCount; + return defaultShowCount; } List currentRangeListForEntity() { diff --git a/lib/src/components/selection/brn_flat_selection.dart b/lib/src/components/selection/brn_flat_selection.dart index 8fd19c9a..7d8b03d0 100644 --- a/lib/src/components/selection/brn_flat_selection.dart +++ b/lib/src/components/selection/brn_flat_selection.dart @@ -82,7 +82,7 @@ class _BrnFlatSelectionState extends State widget.controller?.addListener(_handleFlatControllerTick); List firstColumn = []; - if (widget.entityDataList.length > 0) { + if (widget.entityDataList.isNotEmpty) { for (BrnSelectionEntity entity in widget.entityDataList) { if (entity.isSelected) { firstColumn.add(entity); @@ -90,12 +90,12 @@ class _BrnFlatSelectionState extends State } } _originalSelectedItemsList.addAll(firstColumn); - if (firstColumn.length > 0) { + if (firstColumn.isNotEmpty) { for (BrnSelectionEntity firstEntity in firstColumn) { List secondColumn = BrnSelectionUtil.currentSelectListForEntity(firstEntity); _originalSelectedItemsList.addAll(secondColumn); - if (secondColumn.length > 0) { + if (secondColumn.isNotEmpty) { for (BrnSelectionEntity secondEntity in secondColumn) { List thirdColumn = BrnSelectionUtil.currentSelectListForEntity(secondEntity); @@ -151,7 +151,7 @@ class _BrnFlatSelectionState extends State /// 取消 _cancelSelectedOptions() { - if (widget.entityDataList.length <= 0) { + if (widget.entityDataList.isEmpty) { return; } for (BrnSelectionEntity entity in widget.entityDataList) { @@ -173,7 +173,7 @@ class _BrnFlatSelectionState extends State /// 重置 _resetSelectedOptions() { clearController.add(FlatClearEvent()); - if (widget.entityDataList.length > 0) { + if (widget.entityDataList.isNotEmpty) { for (BrnSelectionEntity entity in widget.entityDataList) { _clearUIData(entity); } diff --git a/lib/src/components/selection/brn_more_selection.dart b/lib/src/components/selection/brn_more_selection.dart index b07f6ee0..81165709 100644 --- a/lib/src/components/selection/brn_more_selection.dart +++ b/lib/src/components/selection/brn_more_selection.dart @@ -94,7 +94,7 @@ class _BrnMoreSelectionPageState extends State ), //为了解决 键盘抬起按钮的问题 将按钮移动到 此区域 bottomNavigationBar: Container( - height: 80, + height: 80 + _getBottomAreaHeight(), child: Row( children: [ _buildLeftSlide(context), @@ -266,6 +266,10 @@ class _BrnMoreSelectionPageState extends State }); } } + + double _getBottomAreaHeight() { + return MediaQuery.of(context).padding.bottom; + } } /// 底部的重置+确定 diff --git a/lib/src/components/selection/brn_selection_util.dart b/lib/src/components/selection/brn_selection_util.dart index 69b488d8..ae759f18 100644 --- a/lib/src/components/selection/brn_selection_util.dart +++ b/lib/src/components/selection/brn_selection_util.dart @@ -48,14 +48,14 @@ class BrnSelectionUtil { rootEntity = rootEntity.parent!; } - if (rootEntity.children.length > 0) { + if (rootEntity.children.isNotEmpty) { level = level > 1 ? level : 1; for (BrnSelectionEntity firstLevelEntity in rootEntity.children) { - if (firstLevelEntity.children.length > 0) { + if (firstLevelEntity.children.isNotEmpty) { level = level > 2 ? level : 2; for (BrnSelectionEntity secondLevelEntity in firstLevelEntity.children) { - if (secondLevelEntity.children.length > 0) { + if (secondLevelEntity.children.isNotEmpty) { level = 3; break; } @@ -104,7 +104,7 @@ class BrnSelectionUtil { filledCustomInputItem = entity; break; } - if (entity.children.length > 0) { + if (entity.children.isNotEmpty) { filledCustomInputItem = getFilledCustomInputItem(entity.children); } if (filledCustomInputItem != null) { diff --git a/lib/src/components/selection/brn_selection_view.dart b/lib/src/components/selection/brn_selection_view.dart index 1843df76..905e71f0 100644 --- a/lib/src/components/selection/brn_selection_view.dart +++ b/lib/src/components/selection/brn_selection_view.dart @@ -11,7 +11,7 @@ import 'package:flutter/material.dart'; /// 配置 类型为 Range 展示时,每行 tag 的数量 /// [index] 第几个 menu /// [entity] index 对应的 筛选对象 -typedef BrnConfigTagCountPerRow(int index, BrnSelectionEntity entity); +typedef BrnConfigTagCountPerRow = Function(int index, BrnSelectionEntity entity); /// [menuTitle] 设置自定义 menu 的Title文案 /// [isMenuTitleHighLight] 设置自定义 menu 的 title 是否高亮 @@ -132,10 +132,7 @@ class BrnSelectionView extends StatefulWidget { } @override - State createState() { - // TODO: implement createState - return BrnSelectionViewState(); - } + State createState() => BrnSelectionViewState(); } class BrnSelectionViewState extends State { @@ -158,7 +155,7 @@ class BrnSelectionViewState extends State { @override Widget build(BuildContext context) { - if (widget.originalSelectionData.length > 0) { + if (widget.originalSelectionData.isNotEmpty) { widget.originalSelectionData.forEach((f) => f.configRelationship()); return BrnSelectionMenuWidget( context: context, @@ -254,7 +251,7 @@ class BrnSelectionViewState extends State { void _openMore(BrnSelectionEntity entity, {BrnOnCustomFloatingLayerClick? onCustomFloatingLayerClick}) { - if (entity.children.length > 0) { + if (entity.children.isNotEmpty) { Navigator.of(context).push(PageRouteBuilder( opaque: false, pageBuilder: (context, animation, second) { diff --git a/lib/src/components/selection/controller/brn_selection_view_controller.dart b/lib/src/components/selection/controller/brn_selection_view_controller.dart index 2dc25955..1da1450c 100644 --- a/lib/src/components/selection/controller/brn_selection_view_controller.dart +++ b/lib/src/components/selection/controller/brn_selection_view_controller.dart @@ -1,5 +1,4 @@ import 'package:bruno/src/utils/brn_event_bus.dart'; -import "package:flutter/foundation.dart"; import 'package:flutter/material.dart'; class BrnSelectionListViewController extends ChangeNotifier { diff --git a/lib/src/components/selection/controller/brn_selection_view_date_picker_controller.dart b/lib/src/components/selection/controller/brn_selection_view_date_picker_controller.dart index 7a121008..092bcfd5 100644 --- a/lib/src/components/selection/controller/brn_selection_view_date_picker_controller.dart +++ b/lib/src/components/selection/controller/brn_selection_view_date_picker_controller.dart @@ -1,4 +1,3 @@ -import "package:flutter/foundation.dart"; import 'package:flutter/material.dart'; class BrnSelectionDatePickerController extends ChangeNotifier { diff --git a/lib/src/components/selection/widget/brn_flat_selection_item.dart b/lib/src/components/selection/widget/brn_flat_selection_item.dart index 2154786c..12b781e2 100644 --- a/lib/src/components/selection/widget/brn_flat_selection_item.dart +++ b/lib/src/components/selection/widget/brn_flat_selection_item.dart @@ -1,5 +1,4 @@ import 'dart:async'; -import 'dart:ui'; import 'package:bruno/src/components/line/brn_line.dart'; import 'package:bruno/src/components/picker/base/brn_picker_title_config.dart'; @@ -179,9 +178,7 @@ class __FilterCommonTypeWidgetState extends State<_FilterCommonTypeWidget> { ), Visibility( visible: widget.selectionEntity - .currentShowTagByExpanded(isExpanded) - .length > - 0, + .currentShowTagByExpanded(isExpanded).isNotEmpty, child: Container( padding: EdgeInsets.only(top: 12), child: _buildOptionWidgets(), diff --git a/lib/src/components/selection/widget/brn_layer_more_selection_page.dart b/lib/src/components/selection/widget/brn_layer_more_selection_page.dart index 24880dd1..bac2587a 100644 --- a/lib/src/components/selection/widget/brn_layer_more_selection_page.dart +++ b/lib/src/components/selection/widget/brn_layer_more_selection_page.dart @@ -133,6 +133,7 @@ class _BrnLayerMoreSelectionPageState extends State .colorTextBase, ), onPressed: () { + BrnSelectionUtil.resetSelectionDatas(widget.entityData); //将选中的筛选项返回 _originalSelectedItemsList.forEach((data) { data.isSelected = true; @@ -140,7 +141,7 @@ class _BrnLayerMoreSelectionPageState extends State Navigator.pop(context, widget.entityData); }, ), - brightness: Brightness.light, + systemOverlayStyle: SystemUiOverlayStyle.dark, backgroundColor: Colors.white, title: Text( '选择${widget.entityData.title}', @@ -340,6 +341,8 @@ class _BrnLayerMoreSelectionPageState extends State padding: const EdgeInsets.only(left: 20), child: Text( name, + maxLines: 2, + overflow: TextOverflow.ellipsis, style: textStyle, ), ), @@ -428,7 +431,7 @@ class _BrnLayerMoreSelectionPageState extends State Widget _buildRightMultiItem(BrnSelectionEntity? entity) { if (entity == null) { - return SizedBox.shrink(); + return const SizedBox.shrink(); } else { return Row( children: [ @@ -455,7 +458,7 @@ class _BrnLayerMoreSelectionPageState extends State Widget _buildRightSingleItem(BrnSelectionEntity? entity) { if (entity == null) { - return SizedBox.shrink(); + return const SizedBox.shrink(); } else { return Text(entity.title, textAlign: TextAlign.left, diff --git a/lib/src/components/selection/widget/brn_selection_animate_widget.dart b/lib/src/components/selection/widget/brn_selection_animate_widget.dart index 7cd9c1cd..c83821de 100644 --- a/lib/src/components/selection/widget/brn_selection_animate_widget.dart +++ b/lib/src/components/selection/widget/brn_selection_animate_widget.dart @@ -1,8 +1,6 @@ import 'package:bruno/src/components/selection/controller/brn_selection_view_controller.dart'; import 'package:flutter/material.dart'; -typedef void MaskClickFunction(int index); - class BrnSelectionAnimationWidget extends StatefulWidget { final BrnSelectionListViewController controller; final Widget view; diff --git a/lib/src/components/selection/widget/brn_selection_common_item_widget.dart b/lib/src/components/selection/widget/brn_selection_common_item_widget.dart index 7cae62f9..b512dfc5 100644 --- a/lib/src/components/selection/widget/brn_selection_common_item_widget.dart +++ b/lib/src/components/selection/widget/brn_selection_common_item_widget.dart @@ -6,8 +6,6 @@ import 'package:bruno/src/utils/brn_tools.dart'; import 'package:bruno/src/utils/css/brn_css_2_text.dart'; import 'package:flutter/material.dart'; -typedef void ItemSelectFunction(BrnSelectionEntity entity); - class BrnSelectionCommonItemWidget extends StatelessWidget { final BrnSelectionEntity item; final Color? backgroundColor; @@ -16,7 +14,7 @@ class BrnSelectionCommonItemWidget extends StatelessWidget { final bool isFirstLevel; final bool isMoreSelectionListType; - final ItemSelectFunction? itemSelectFunction; + final ValueChanged? itemSelectFunction; final BrnSelectionConfig? themeData; @@ -34,8 +32,8 @@ class BrnSelectionCommonItemWidget extends StatelessWidget { @override Widget build(BuildContext context) { - var checkbox; - if (!item.isUnLimit() && (item.children.length == 0)) { + Container checkbox; + if (!item.isUnLimit() && (item.children.isEmpty)) { if (item.isInLastLevel() && item.hasCheckBoxBrother()) { checkbox = Container( padding: EdgeInsets.only(left: 6), @@ -129,7 +127,7 @@ class BrnSelectionCommonItemWidget extends StatelessWidget { if (isHighLight(item)) { return true; } else { - return item.hasCheckBoxBrother() && item.selectedList().length > 0; + return item.hasCheckBoxBrother() && item.selectedList().isNotEmpty; } } @@ -155,7 +153,7 @@ class BrnSelectionCommonItemWidget extends StatelessWidget { } else { var unLimited = item.children.where((f) => f.isSelected && f.isUnLimit()).toList(); - if (unLimited.length > 0) { + if (unLimited.isNotEmpty) { return '(全部)'; } } diff --git a/lib/src/components/selection/widget/brn_selection_date_range_item_widget.dart b/lib/src/components/selection/widget/brn_selection_date_range_item_widget.dart index f789193c..b1079422 100644 --- a/lib/src/components/selection/widget/brn_selection_date_range_item_widget.dart +++ b/lib/src/components/selection/widget/brn_selection_date_range_item_widget.dart @@ -10,9 +10,6 @@ import 'package:bruno/src/utils/i18n/brn_date_picker_i18n.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -typedef void OnRangeChangedFunction(String minInput, String maxInput); -typedef void OnTappedFunction(); - const String _defaultDateFormat = 'yyyy年MM月dd日'; // ignore: must_be_immutable @@ -31,7 +28,7 @@ class BrnSelectionDateRangeItemWidget extends StatefulWidget { final TextEditingController minTextEditingController; final TextEditingController maxTextEditingController; - final OnTappedFunction? onTapped; + final VoidCallback? onTapped; BrnSelectionConfig themeData; @@ -58,13 +55,13 @@ class _BrnSelectionDateRangeItemWidgetState @override void initState() { - var minDateTime; + DateTime? minDateTime; if (widget.item.customMap != null && widget.item.customMap!['min'] != null) { minDateTime = DateTimeFormatter.convertIntValueToDateTime( widget.item.customMap!['min']); } - var maxDateTime; + DateTime? maxDateTime; if (widget.item.customMap != null && widget.item.customMap!['max'] != null) { maxDateTime = DateTimeFormatter.convertIntValueToDateTime( @@ -256,7 +253,6 @@ class _BrnSelectionDateRangeItemWidgetState @override void dispose() { - // TODO: implement dispose _datePickerController.hide(); super.dispose(); } diff --git a/lib/src/components/selection/widget/brn_selection_datepicker_animate_widget.dart b/lib/src/components/selection/widget/brn_selection_datepicker_animate_widget.dart index ebc4ec00..7143ccc0 100644 --- a/lib/src/components/selection/widget/brn_selection_datepicker_animate_widget.dart +++ b/lib/src/components/selection/widget/brn_selection_datepicker_animate_widget.dart @@ -1,8 +1,6 @@ import 'package:bruno/src/components/selection/controller/brn_selection_view_date_picker_controller.dart'; import 'package:flutter/material.dart'; -typedef void MaskClickFunction(int index); - class BrnSelectionDatePickerAnimationWidget extends StatefulWidget { final BrnSelectionDatePickerController controller; final Widget view; diff --git a/lib/src/components/selection/widget/brn_selection_list_widget.dart b/lib/src/components/selection/widget/brn_selection_list_widget.dart index c0d32144..52a9d1f2 100644 --- a/lib/src/components/selection/widget/brn_selection_list_widget.dart +++ b/lib/src/components/selection/widget/brn_selection_list_widget.dart @@ -10,17 +10,15 @@ import 'package:bruno/src/theme/configs/brn_selection_config.dart'; import 'package:bruno/src/utils/brn_tools.dart'; import 'package:flutter/material.dart'; -typedef void SingleListItemSelect( +typedef SingleListItemSelect = void Function( int listIndex, int index, BrnSelectionEntity entity); -typedef void ListBgClickFunction(); - // ignore: must_be_immutable class BrnListSelectionGroupWidget extends StatefulWidget { final BrnSelectionEntity entity; final double maxContentHeight; final bool showSelectedCount; - final ListBgClickFunction? bgClickFunction; + final VoidCallback? bgClickFunction; final BrnOnRangeSelectionConfirm? onSelectionConfirm; BrnSelectionConfig themeData; @@ -434,7 +432,7 @@ class _BrnSelectionGroupViewState extends State { int _getInitialSelectIndex(List levelList) { int index = -1; - if (levelList.length == 0) { + if (levelList.isEmpty) { return index; } @@ -555,11 +553,11 @@ class _BrnSelectionGroupViewState extends State { } _processSelectedStatus(BrnSelectionEntity entity) { - if (entity.children.length > 0) { + if (entity.children.isNotEmpty) { entity.children.forEach((f) => _processSelectedStatus(f)); if (entity.hasCheckBoxBrother()) { entity.isSelected = - entity.children.where((_) => _.isSelected).length > 0; + entity.children.where((_) => _.isSelected).isNotEmpty; } } } diff --git a/lib/src/components/selection/widget/brn_selection_menu_item_widget.dart b/lib/src/components/selection/widget/brn_selection_menu_item_widget.dart index cf74bb03..bae2214f 100644 --- a/lib/src/components/selection/widget/brn_selection_menu_item_widget.dart +++ b/lib/src/components/selection/widget/brn_selection_menu_item_widget.dart @@ -3,14 +3,12 @@ import 'package:bruno/src/theme/configs/brn_selection_config.dart'; import 'package:bruno/src/utils/brn_tools.dart'; import 'package:flutter/material.dart'; -typedef void ItemClickFunction(); - // ignore: must_be_immutable class BrnSelectionMenuItemWidget extends StatelessWidget { final String title; final bool isHighLight; final bool active; - final ItemClickFunction? itemClickFunction; + final VoidCallback? itemClickFunction; BrnSelectionConfig themeData; diff --git a/lib/src/components/selection/widget/brn_selection_menu_widget.dart b/lib/src/components/selection/widget/brn_selection_menu_widget.dart index 18a0a187..0deddc5b 100644 --- a/lib/src/components/selection/widget/brn_selection_menu_widget.dart +++ b/lib/src/components/selection/widget/brn_selection_menu_widget.dart @@ -15,9 +15,9 @@ import 'package:bruno/src/utils/brn_tools.dart'; import 'package:bruno/src/utils/i18n/brn_date_picker_i18n.dart'; import 'package:flutter/material.dart'; -typedef bool BrnOnMenuItemClick(int index); +typedef BrnOnMenuItemClick = bool Function(int index); -typedef void BrnOnRangeSelectionConfirm(BrnSelectionEntity results, +typedef BrnOnRangeSelectionConfirm = void Function(BrnSelectionEntity results, int firstIndex, int secondIndex, int thirdIndex); class BrnSelectionMenuWidget extends StatefulWidget { @@ -302,7 +302,7 @@ class _BrnSelectionMenuWidgetState extends State { bgClickFunction: () { setState(() { menuItemActiveState[listViewController.menuIndex] = false; - if (entity.selectedListWithoutUnlimit().length > 0) { + if (entity.selectedListWithoutUnlimit().isNotEmpty) { menuItemHighlightState[listViewController.menuIndex] = true; } listViewController.hide(); @@ -329,7 +329,7 @@ class _BrnSelectionMenuWidgetState extends State { bgClickFunction: () { setState(() { menuItemActiveState[listViewController.menuIndex] = false; - if (entity.selectedListWithoutUnlimit().length > 0) { + if (entity.selectedListWithoutUnlimit().isNotEmpty) { menuItemHighlightState[listViewController.menuIndex] = true; } listViewController.hide(); @@ -375,11 +375,11 @@ class _BrnSelectionMenuWidgetState extends State { BrnSelectionUtil.currentSelectListForEntity(entity); List secondColumn = []; List thirdColumn = []; - if (firstColumn.length > 0) { + if (firstColumn.isNotEmpty) { for (BrnSelectionEntity firstEntity in firstColumn) { secondColumn .addAll(BrnSelectionUtil.currentSelectListForEntity(firstEntity)); - if (secondColumn.length > 0) { + if (secondColumn.isNotEmpty) { for (BrnSelectionEntity secondEntity in secondColumn) { thirdColumn.addAll( BrnSelectionUtil.currentSelectListForEntity(secondEntity)); @@ -388,7 +388,7 @@ class _BrnSelectionMenuWidgetState extends State { } } - if (firstColumn.length == 0 || firstColumn.length > 1) { + if (firstColumn.isEmpty || firstColumn.length > 1) { title = entity.title; } else { /// 第一列选中了一个,为【不限】类型,使用上一级别的名字展示。 @@ -401,7 +401,7 @@ class _BrnSelectionMenuWidgetState extends State { BrnSelectionFilterType.dateRangeCalendar) { title = _getDateAndRangeTitle(firstColumn, entity); } else { - if (secondColumn.length == 0 || secondColumn.length > 1) { + if (secondColumn.isEmpty || secondColumn.length > 1) { title = firstColumn[0].title; } else { /// 第二列选中了一个,为【不限】类型,使用上一级别的名字展示。 @@ -415,7 +415,7 @@ class _BrnSelectionMenuWidgetState extends State { BrnSelectionFilterType.dateRangeCalendar) { title = _getDateAndRangeTitle(secondColumn, firstColumn[0]); } else { - if (thirdColumn.length == 0 || thirdColumn.length > 1) { + if (thirdColumn.isEmpty || thirdColumn.length > 1) { title = secondColumn[0].title; } else { /// 第三列选中了一个,为【不限】类型,使用上一级别的名字展示。 @@ -525,7 +525,7 @@ class _BrnSelectionMenuWidgetState extends State { void _refreshSelectionMenuTitle(int index, BrnSelectionEntity entity) { if (entity.filterType == BrnSelectionFilterType.more) { - if (entity.allSelectedList().length > 0) { + if (entity.allSelectedList().isNotEmpty) { menuItemHighlightState[index] = true; } else { menuItemHighlightState[index] = false; @@ -536,7 +536,7 @@ class _BrnSelectionMenuWidgetState extends State { if (title != null) { titles[index] = title; } - if (entity.selectedListWithoutUnlimit().length > 0) { + if (entity.selectedListWithoutUnlimit().isNotEmpty) { menuItemHighlightState[index] = true; } else if (!BrunoTools.isEmpty(entity.customTitle)) { menuItemHighlightState[index] = entity.isCustomTitleHighLight; diff --git a/lib/src/components/selection/widget/brn_selection_more_item_widget.dart b/lib/src/components/selection/widget/brn_selection_more_item_widget.dart index dddc1aa1..e2ac2a89 100644 --- a/lib/src/components/selection/widget/brn_selection_more_item_widget.dart +++ b/lib/src/components/selection/widget/brn_selection_more_item_widget.dart @@ -143,9 +143,7 @@ class __FilterCommonTypeWidgetState extends State<_FilterCommonTypeWidget> { //标签的筛选条件 Visibility( visible: widget.selectionEntity - .currentShowTagByExpanded(isExpanded) - .length > - 0, + .currentShowTagByExpanded(isExpanded).isNotEmpty, child: Padding( padding: EdgeInsets.only(top: 12), child: _buildSelectionTag(), diff --git a/lib/src/components/selection/widget/brn_selection_range_input_item_widget.dart b/lib/src/components/selection/widget/brn_selection_range_input_item_widget.dart index 0372558d..ae412365 100644 --- a/lib/src/components/selection/widget/brn_selection_range_input_item_widget.dart +++ b/lib/src/components/selection/widget/brn_selection_range_input_item_widget.dart @@ -4,8 +4,7 @@ import 'package:bruno/src/utils/brn_event_bus.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -typedef void OnRangeChangedFunction(String minInput, String maxInput); -typedef void OnFocusChangedFunction(bool focus); +typedef RangeChangedCallback = void Function(String minInput, String maxInput); /// 清空自定义范围输入框焦点的事件类 class ClearSelectionFocusEvent {} @@ -13,8 +12,8 @@ class ClearSelectionFocusEvent {} class BrnSelectionRangeItemWidget extends StatefulWidget { final BrnSelectionEntity item; - final OnRangeChangedFunction? onRangeChanged; - final OnFocusChangedFunction? onFocusChanged; + final RangeChangedCallback? onRangeChanged; + final ValueChanged? onFocusChanged; final bool isShouldClearText; diff --git a/lib/src/components/selection/widget/brn_selection_range_widget.dart b/lib/src/components/selection/widget/brn_selection_range_widget.dart index b9d28714..3b7ec3c5 100644 --- a/lib/src/components/selection/widget/brn_selection_range_widget.dart +++ b/lib/src/components/selection/widget/brn_selection_range_widget.dart @@ -18,9 +18,6 @@ import 'package:bruno/src/utils/brn_event_bus.dart'; import 'package:bruno/src/utils/brn_text_util.dart'; import 'package:bruno/src/utils/brn_tools.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/widgets.dart'; - -typedef void BrnOnRangeSelectionBgClick(); class BrnRangeSelectionGroupWidget extends StatefulWidget { static final double screenWidth = @@ -29,7 +26,7 @@ class BrnRangeSelectionGroupWidget extends StatefulWidget { final BrnSelectionEntity entity; final double maxContentHeight; final bool showSelectedCount; - final BrnOnRangeSelectionBgClick? bgClickFunction; + final VoidCallback? bgClickFunction; final BrnOnRangeSelectionConfirm? onSelectionConfirm; final int? rowCount; @@ -254,7 +251,7 @@ class _BrnRangeSelectionGroupWidgetState widget.rowCount!; } - var tagContainer = (tagFilterList.length) > 0 + var tagContainer = tagFilterList.isNotEmpty ? Container( alignment: Alignment.centerLeft, padding: EdgeInsets.only(left: 20, right: 20, top: 20, bottom: 20), @@ -276,7 +273,7 @@ class _BrnRangeSelectionGroupWidgetState ) : Container(); - var content; + Widget? content; for (BrnSelectionEntity item in subFilterList) { if (item.filterType == BrnSelectionFilterType.range) { content = BrnSelectionRangeItemWidget( @@ -408,7 +405,7 @@ class _BrnRangeSelectionGroupWidgetState widget.entity.children[_tabController.index].children; List selectItems = subFilterList.where((f) => f.isSelected).toList(); - if (selectItems.length > 0) { + if (selectItems.isNotEmpty) { _firstList[_tabController.index].isSelected = true; } else { _firstList[_tabController.index].isSelected = false; @@ -596,7 +593,7 @@ class _BrnRangeSelectionGroupWidgetState f.isSelected) .toList(); - if (ranges.length > 0) { + if (ranges.isNotEmpty) { return ranges[0]; } return null; @@ -658,9 +655,7 @@ class _BrnRangeSelectionGroupWidgetState .where((_) => _.filterType == BrnSelectionFilterType.date || _.filterType == BrnSelectionFilterType.dateRangeCalendar) - .toList() - .length > - 0; + .toList().isNotEmpty; /// 查找第二层级 if (!hasCalendarItem) { diff --git a/lib/src/components/selection/widget/brn_selection_single_list_widget.dart b/lib/src/components/selection/widget/brn_selection_single_list_widget.dart index c7f30183..8db3012a 100644 --- a/lib/src/components/selection/widget/brn_selection_single_list_widget.dart +++ b/lib/src/components/selection/widget/brn_selection_single_list_widget.dart @@ -43,7 +43,7 @@ class BrnSelectionSingleListWidget extends StatefulWidget { /// 当前 Items 所在的层级 currentListIndex = BrnSelectionUtil.getCurrentListIndex( - items.length > 0 ? items[0] : null); + items.isNotEmpty ? items[0] : null); _selectedItems = items.where((f) => f.isSelected).toList(); } @@ -153,7 +153,7 @@ class _BrnSelectionSingleListWidgetState /// Warning !!! /// (两列、三列时)第一列节点是否被选中取决于它的子节点是否被选中, /// 只有当它子节点被选中时才会认为第一列的节点相应被选中。 - if (widget.items.length > 0) { + if (widget.items.isNotEmpty) { widget.items[0].parent?.isSelected = (widget.items[0].parent?.children .where((BrnSelectionEntity f) => f.isSelected) .length ?? @@ -204,8 +204,17 @@ class _BrnSelectionSingleListWidgetState void configMultiLevelList( BrnSelectionEntity selectedEntity, int currentListIndex) { - /// 单选,清除同一级别选中的状态,则其他的设置为未选中。 - if (BrnSelectionFilterType.radio == selectedEntity.filterType) { + /// 选中【不限】清除同一级别其他的状态 + if(selectedEntity.isUnLimit()){ + selectedEntity.parent?.children + .where((f) => f != selectedEntity) + .forEach((f) { + f.clearChildSelection(); + f.isSelected = false; + }); + selectedEntity.isSelected = true; + } else if (BrnSelectionFilterType.radio == selectedEntity.filterType) { + /// 单选,清除同一级别选中的状态,则其他的设置为未选中。 selectedEntity.parent?.children .where((f) => f != selectedEntity) .forEach((f) { @@ -214,16 +223,6 @@ class _BrnSelectionSingleListWidgetState }); selectedEntity.isSelected = true; } else if (BrnSelectionFilterType.checkbox == selectedEntity.filterType) { - /// 选中【不限】清除同一级别其他的状态 - if (selectedEntity.isUnLimit()) { - selectedEntity.parent?.children - .where((f) => f != selectedEntity) - .forEach((f) { - f.clearChildSelection(); - f.isSelected = false; - }); - selectedEntity.isSelected = true; - } else { ///清除【不限】类型。 List brotherItems; if (selectedEntity.parent == null) { @@ -238,7 +237,6 @@ class _BrnSelectionSingleListWidgetState } } selectedEntity.isSelected = !selectedEntity.isSelected; - } } } } diff --git a/lib/src/components/sugsearch/brn_search_text.dart b/lib/src/components/sugsearch/brn_search_text.dart index ebd7befb..343a2f1d 100644 --- a/lib/src/components/sugsearch/brn_search_text.dart +++ b/lib/src/components/sugsearch/brn_search_text.dart @@ -1,8 +1,8 @@ import 'package:bruno/src/constants/brn_asset_constants.dart'; import 'package:bruno/src/theme/brn_theme_configurator.dart'; import 'package:bruno/src/utils/brn_tools.dart'; -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; /// 搜索框内容变化回调 typedef BrnOnSearchTextChange = void Function(String content); @@ -62,6 +62,11 @@ class BrnSearchText extends StatefulWidget { /// 用于控制键盘动作 final TextInputAction? textInputAction; + + final TextInputType? textInputType; + + final List? inputFormatters; + final TextEditingController? controller; final FocusNode? focusNode; @@ -108,6 +113,8 @@ class BrnSearchText extends StatefulWidget { this.focusNode, this.autoFocus = false, this.textInputAction, + this.inputFormatters, + this.textInputType, }) : super(key: key); @override @@ -150,7 +157,6 @@ class _SearchTextState extends State { @override void dispose() { - // TODO: implement dispose super.dispose(); tmpController?.dispose(); focusNode!.removeListener(_handleFocusNodeChangeListenerTick); @@ -203,16 +209,14 @@ class _SearchTextState extends State { autofocus: widget.autoFocus, textInputAction: this.widget.textInputAction, focusNode: focusNode, - // 控制器属性,控制正在编辑的文本。 controller: textEditingController, - // 光标颜色属性,绘制光标时使用的颜色。 + keyboardType: widget.textInputType, + inputFormatters: widget.inputFormatters, cursorColor: BrnThemeConfigurator.instance .getConfig() .commonConfig .brandPrimary, - // 光标宽度属性,光标的厚度,默认是2.0。 cursorWidth: 2.0, - // 样式属性,用于正在编辑的文本的样式。 style: widget.textStyle ?? TextStyle( textBaseline: TextBaseline.alphabetic, @@ -221,18 +225,14 @@ class _SearchTextState extends State { .commonConfig .colorTextBase, fontSize: 16), - // 装饰(`decoration`)属性,在文本字段周围显示的装饰。 decoration: InputDecoration( - // 边框属性,装饰的容器周围绘制的形状。 border: InputBorder.none, contentPadding: EdgeInsets.only(left: 8, right: 6), // 填充颜色属性,填充装饰容器的颜色。 fillColor: widget.innerColor, // 是密集属性,输入子项是否是密集形式的一部分(即使用较少的垂直空间)。 isDense: true, - // 填充属性,如果为`true`,则装饰的容器将填充fillColor颜色。 filled: true, - // 提示样式属性,用于提示文本(`hintText`)的样式。 hintStyle: widget.hintStyle ?? TextStyle( fontSize: 16, @@ -240,9 +240,7 @@ class _SearchTextState extends State { textBaseline: TextBaseline.alphabetic, color: Color(0xff999999), ), - // 提示文本属性,提示字段接受哪种输入的文本。 hintText: widget.hintText ?? "请输入搜索内容", - // 不显示计数面板 counterText: '', ), // 在改变属性,当正在编辑的文本发生更改时调用。 diff --git a/lib/src/components/switch/brn_switch_button.dart b/lib/src/components/switch/brn_switch_button.dart new file mode 100644 index 00000000..98f59bf2 --- /dev/null +++ b/lib/src/components/switch/brn_switch_button.dart @@ -0,0 +1,75 @@ +import 'package:bruno/src/theme/brn_theme.dart'; +import 'package:flutter/material.dart'; + +import 'brn_switch_button_base.dart'; + + +/// 描述: 开关按钮 +class BrnSwitchButton extends StatefulWidget { + final Size size; + + ///选中的状态 + final bool value; + + ///是否可以交互 + final bool enabled; + + ///点击事件 + final ValueChanged onChanged; + + ///未选中时边框的颜色 + final Color? borderColor; + + BrnSwitchButton({ + Key? key, + required this.value, + required this.onChanged, + this.enabled = true, + this.size = const Size(42, 26), + this.borderColor, + }) : super(key: key); + + @override + _BrnSwitchButtonState createState() => _BrnSwitchButtonState(); +} + +class _BrnSwitchButtonState extends State { + @override + Widget build(BuildContext context) { + return BrnBaseSwitchButton( + borderColor: widget.borderColor ?? _getBorderColor(), + value: widget.value, + enabled: widget.enabled, + size: widget.size, + trackColor: _getTrackColor(), + thumbColor: widget.enabled ? Colors.white : Color(0xFFFDFDFD), + onChanged: widget.enabled ? widget.onChanged : null, + ); + } + + Color _getTrackColor() { + if (widget.value) { + return widget.enabled + ? BrnThemeConfigurator.instance.getConfig().commonConfig.brandPrimary + : BrnThemeConfigurator.instance + .getConfig() + .commonConfig + .brandPrimary + .withAlpha(20); + } else { + return widget.enabled ? Color(0xFFFAFAFA) : Color(0xFFeeeeee); + } + } + + Color _getBorderColor() { + if (widget.value) { + return _getTrackColor(); + } else { + if (widget.enabled) { + return const Color(0xffeeeeee); + } else { + return const Color(0xffeeeeee); + } + } + } +} diff --git a/lib/src/components/switch/brn_switch_button_base.dart b/lib/src/components/switch/brn_switch_button_base.dart new file mode 100644 index 00000000..3e2a3bf7 --- /dev/null +++ b/lib/src/components/switch/brn_switch_button_base.dart @@ -0,0 +1,93 @@ +import 'package:flutter/material.dart'; + +const double _borderWidth = 1.5; + +class BrnBaseSwitchButton extends StatelessWidget { + final Size size; + + /// Whether this switch is on or off. + /// + /// This property must not be null. + final bool value; + + /// can click + final bool enabled; + + final ValueChanged? onChanged; + + final Color borderColor; + + final Color? trackColor; + + final Color thumbColor; + + const BrnBaseSwitchButton({ + Key? key, + required this.value, + required this.onChanged, + required this.size, + this.thumbColor = Colors.white, + this.trackColor, + this.borderColor = const Color(0xffeeeeee), + this.enabled = false, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: () { + if (enabled) { + onChanged?.call(!value); + } + }, + child: Stack( + alignment: value ? Alignment.centerRight : Alignment.centerLeft, + children: [ + Container( + height: size.height, + width: size.width, + decoration: BoxDecoration( + color: trackColor, + border: Border.all( + color: value ? Colors.transparent : borderColor, + width: _borderWidth), + borderRadius: + BorderRadius.all(Radius.circular(size.height / 2)), + ), + ), + _getThumb(value) + ], + ), + ); + } + + Positioned _getThumb(bool value) { + return (value) + ? Positioned( + child: Padding( + padding: EdgeInsets.only(right: _borderWidth), + child: Container( + height: size.height - 2 * _borderWidth, + width: size.height - 2 * _borderWidth, + decoration: BoxDecoration( + color: thumbColor, + borderRadius: BorderRadius.all( + Radius.circular(size.height / 2 - _borderWidth)), + ), + ), + ), + ) + : Positioned( + child: Container( + height: size.height, + width: size.height, + decoration: BoxDecoration( + color: thumbColor, + border: Border.all(color: borderColor, width: _borderWidth), + borderRadius: + BorderRadius.all(Radius.circular(size.height / 2)), + ), + ), + ); + } +} diff --git a/lib/src/components/tabbar/bottom/brn_bottom_tab_bar_main.dart b/lib/src/components/tabbar/bottom/brn_bottom_tab_bar_main.dart index 70776a9e..948f903b 100644 --- a/lib/src/components/tabbar/bottom/brn_bottom_tab_bar_main.dart +++ b/lib/src/components/tabbar/bottom/brn_bottom_tab_bar_main.dart @@ -4,8 +4,6 @@ import 'dart:collection' show Queue; import 'dart:math' as math; import 'package:bruno/bruno.dart'; -import 'package:bruno/src/components/tabbar/bottom/brn_bottom_tab_bar_item.dart'; -import 'package:bruno/src/theme/configs/brn_all_config.dart'; import 'package:flutter/material.dart'; /// 定义一些UI常量,根据UI稿进行填写 @@ -33,21 +31,18 @@ class BrnBottomTabBar extends StatefulWidget { required this.items, this.onTap, this.currentIndex = 0, - BrnBottomTabBarDisplayType type = BrnBottomTabBarDisplayType.fixed, + this.type = BrnBottomTabBarDisplayType.fixed, this.fixedColor, this.iconSize = 24.0, this.isAnimation = false, this.badgeColor, this.isInkResponse = false, - }) : assert(items.length >= 1), + }) : assert(items.isNotEmpty), assert( items.every((BrnBottomTabBarItem item) => item.title != null) == true, 'Every item must have a non-null title', ), assert(0 <= currentIndex && currentIndex < items.length), - type = items.length <= 3 - ? BrnBottomTabBarDisplayType.fixed - : BrnBottomTabBarDisplayType.shifting, super(key: key); /// 动画是否可见,默认:true @@ -97,8 +92,12 @@ class _BottomTabBarState extends State with TickerProviderState Tween(begin: 1.0, end: 1.5); void _resetState() { - for (AnimationController controller in _controllers) controller.dispose(); - for (_Circle circle in _circles) circle.dispose(); + for (AnimationController controller in _controllers) { + controller.dispose(); + } + for (_Circle circle in _circles) { + circle.dispose(); + } _circles.clear(); _controllers = @@ -134,8 +133,12 @@ class _BottomTabBarState extends State with TickerProviderState @override void dispose() { - for (AnimationController controller in _controllers) controller.dispose(); - for (_Circle circle in _circles) circle.dispose(); + for (AnimationController controller in _controllers) { + controller.dispose(); + } + for (_Circle circle in _circles) { + circle.dispose(); + } super.dispose(); } @@ -193,8 +196,9 @@ class _BottomTabBarState extends State with TickerProviderState _controllers[oldWidget.currentIndex].reverse(); _controllers[widget.currentIndex].forward(); } else { - if (_backgroundColor != widget.items[widget.currentIndex].backgroundColor) + if (_backgroundColor != widget.items[widget.currentIndex].backgroundColor) { _backgroundColor = widget.items[widget.currentIndex].backgroundColor; + } } } @@ -213,7 +217,7 @@ class _BottomTabBarState extends State with TickerProviderState themeColor = themeData.primaryColor; break; case Brightness.dark: - themeColor = themeData.accentColor; + themeColor = themeData.colorScheme.secondary; break; } final ColorTween colorTween = ColorTween( @@ -429,7 +433,7 @@ class _BottomNavigationTile extends StatelessWidget { break; case BrnBottomTabBarDisplayType.shifting: tweenStart = 16.0; - iconColor = Colors.blue; + iconColor = selected ? BrnThemeConfigurator.instance.getConfig().commonConfig.brandPrimary : null; break; } return Align( @@ -572,6 +576,7 @@ class _BottomNavigationTile extends StatelessWidget { } return GestureDetector( onTap: onTap, + behavior: HitTestBehavior.opaque, child: Column( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -660,8 +665,9 @@ class _RadialPainter extends CustomPainter { if (textDirection != oldPainter.textDirection) return true; if (circles == oldPainter.circles) return false; if (circles.length != oldPainter.circles.length) return true; - for (int i = 0; i < circles.length; i += 1) + for (int i = 0; i < circles.length; i += 1) { if (circles[i] != oldPainter.circles[i]) return true; + } return false; } diff --git a/lib/src/components/tabbar/indicator/brn_fixed_underline_decoration.dart b/lib/src/components/tabbar/indicator/brn_fixed_underline_decoration.dart index b7f15bc1..59f15900 100644 --- a/lib/src/components/tabbar/indicator/brn_fixed_underline_decoration.dart +++ b/lib/src/components/tabbar/indicator/brn_fixed_underline_decoration.dart @@ -2,10 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. - - import 'package:flutter/material.dart'; -import 'package:flutter/widgets.dart'; /// Used with [TabBar.indicator] to draw a horizontal line below the /// selected tab. diff --git a/lib/src/components/tabbar/indicator/brn_triangle_decoration.dart b/lib/src/components/tabbar/indicator/brn_triangle_decoration.dart index ed6219cf..af005ef2 100644 --- a/lib/src/components/tabbar/indicator/brn_triangle_decoration.dart +++ b/lib/src/components/tabbar/indicator/brn_triangle_decoration.dart @@ -201,11 +201,6 @@ class _TriangleDecorationPainter extends BoxPainter { _path.reset(); } - @override - void dispose() { - super.dispose(); - } - @override void paint(Canvas canvas, Offset offset, ImageConfiguration configuration) { assert(configuration.size != null); diff --git a/lib/src/components/tabbar/normal/brn_tab_bar.dart b/lib/src/components/tabbar/normal/brn_tab_bar.dart index 1e813c4f..619ef439 100644 --- a/lib/src/components/tabbar/normal/brn_tab_bar.dart +++ b/lib/src/components/tabbar/normal/brn_tab_bar.dart @@ -134,23 +134,23 @@ class BrnTabBar extends StatefulWidget { this.tagSpacing, this.preLineTagCount, this.tagHeight, - }) : assert(tabs == null || tabs is List) { + }) : assert(tabs != null) { this.themeData ??= BrnTabBarConfig(); - this.themeData = this.themeData!.merge(BrnTabBarConfig( - backgroundColor: backgroundcolor, - tabHeight: tabHeight, - indicatorHeight: indicatorWeight, - indicatorWidth: indicatorWidth, - labelStyle: BrnTextStyle.withStyle(labelStyle), - unselectedLabelStyle: BrnTextStyle.withStyle(unselectedLabelStyle), - tagSpacing: tagSpacing, - preLineTagCount: preLineTagCount, - tagHeight: tagHeight, - )); this.themeData = BrnThemeConfigurator.instance .getConfig(configId: this.themeData!.configId) .tabBarConfig .merge(this.themeData); + this.themeData = this.themeData!.merge(BrnTabBarConfig( + backgroundColor: backgroundcolor, + tabHeight: tabHeight, + indicatorHeight: indicatorWeight, + indicatorWidth: indicatorWidth, + labelStyle: BrnTextStyle.withStyle(labelStyle), + unselectedLabelStyle: BrnTextStyle.withStyle(unselectedLabelStyle), + tagSpacing: tagSpacing, + preLineTagCount: preLineTagCount, + tagHeight: tagHeight, + )); } @override diff --git a/lib/src/components/tag/tagview/brn_delete_tag.dart b/lib/src/components/tag/tagview/brn_delete_tag.dart index 2fb00e75..8f58885b 100644 --- a/lib/src/components/tag/tagview/brn_delete_tag.dart +++ b/lib/src/components/tag/tagview/brn_delete_tag.dart @@ -2,7 +2,6 @@ import 'package:bruno/src/constants/brn_asset_constants.dart'; import 'package:bruno/src/theme/brn_theme.dart'; import 'package:bruno/src/utils/brn_tools.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/widgets.dart'; /// 删除模式的标签 /// 支持下下流式和横向滑动布局 @@ -70,13 +69,13 @@ class BrnDeleteTag extends StatefulWidget { this.themeData}) : super(key: key) { themeData ??= BrnTagConfig(); - themeData = themeData!.merge(BrnTagConfig( - tagBackgroundColor: this.backgroundColor, - tagTextStyle: BrnTextStyle.withStyle(tagTextStyle))); themeData = BrnThemeConfigurator.instance .getConfig(configId: themeData!.configId) .tagConfig .merge(this.themeData); + themeData = themeData!.merge(BrnTagConfig( + tagBackgroundColor: this.backgroundColor, + tagTextStyle: BrnTextStyle.withStyle(tagTextStyle))); } @override @@ -108,7 +107,7 @@ class _BrnDeleteTagState extends State { /// 根据标签集合构建标签 UI Widget _buildContent(List tags) { if (tags.isEmpty) { - return SizedBox.shrink(); + return const SizedBox.shrink(); } List itemList = []; @@ -265,8 +264,9 @@ class BrnDeleteTagController { String result = _tags.removeAt(index); _asyncData(); return result; - } else + } else { return null; + } } /// 删除某个具体内容的标签,成功返回 true,失败返回 false diff --git a/lib/src/components/tag/tagview/brn_select_tag.dart b/lib/src/components/tag/tagview/brn_select_tag.dart index f2aed619..c55ee652 100644 --- a/lib/src/components/tag/tagview/brn_select_tag.dart +++ b/lib/src/components/tag/tagview/brn_select_tag.dart @@ -82,6 +82,10 @@ class BrnSelectTag extends StatefulWidget { assert(initTagState == null || (initTagState!.length <= 1)); } this.themeData ??= BrnTagConfig(); + this.themeData = BrnThemeConfigurator.instance + .getConfig(configId: this.themeData!.configId) + .tagConfig + .merge(this.themeData); this.themeData = this.themeData!.merge(BrnTagConfig( tagBackgroundColor: this.tagBackgroundColor, tagTextStyle: BrnTextStyle.withStyle(this.tagTextStyle), @@ -89,10 +93,6 @@ class BrnSelectTag extends StatefulWidget { tagWidth: this.tagWidth, tagHeight: this.tagHeight, selectedTagBackgroundColor: this.selectedTagBackgroundColor)); - this.themeData = BrnThemeConfigurator.instance - .getConfig(configId: this.themeData!.configId) - .tagConfig - .merge(this.themeData); } @override @@ -223,8 +223,9 @@ class _BrnSelectTagState extends State { void didUpdateWidget(BrnSelectTag oldWidget) { super.didUpdateWidget(oldWidget); // 如果两个数组不相等,重置选中状态 - if (!sameList(oldWidget.tags, widget.tags)) + if (!sameList(oldWidget.tags, widget.tags)) { _tagState = List.filled(widget.tags.length, false); + } } /// 比较两个数组内容是否一致,如果一致,返回 true,否则 false diff --git a/lib/src/theme/base/brn_default_config_utils.dart b/lib/src/theme/base/brn_default_config_utils.dart index fd63dc05..f5a63dc3 100644 --- a/lib/src/theme/base/brn_default_config_utils.dart +++ b/lib/src/theme/base/brn_default_config_utils.dart @@ -424,6 +424,7 @@ class BrnDefaultConfigUtils { iconSize: BrnAppBarTheme.iconSize, configId: BRUNO_CONFIG_ID, systemUiOverlayStyle: SystemUiOverlayStyle.dark, + showDefaultBottom: false, ); /// 内容信息(两列)配置 diff --git a/lib/src/theme/configs/brn_all_config.dart b/lib/src/theme/configs/brn_all_config.dart index fe244f36..fa281b52 100644 --- a/lib/src/theme/configs/brn_all_config.dart +++ b/lib/src/theme/configs/brn_all_config.dart @@ -1,4 +1,4 @@ -import 'package:bruno/bruno.dart'; +import 'package:bruno/src/theme/base/brn_default_config_utils.dart'; import 'package:bruno/src/theme/brn_theme_configurator.dart'; import 'package:bruno/src/theme/configs/brn_abnormal_state_config.dart'; import 'package:bruno/src/theme/configs/brn_action_sheet_config.dart'; diff --git a/lib/src/theme/configs/brn_appbar_config.dart b/lib/src/theme/configs/brn_appbar_config.dart index 5249b3cb..e5d2ee05 100644 --- a/lib/src/theme/configs/brn_appbar_config.dart +++ b/lib/src/theme/configs/brn_appbar_config.dart @@ -27,6 +27,7 @@ class BrnAppBarConfig extends BrnBaseConfig { EdgeInsets? titlePadding, double? iconSize, SystemUiOverlayStyle? systemUiOverlayStyle, + bool? showDefaultBottom, String configId = GLOBAL_CONFIG_ID, }) : _backgroundColor = backgroundColor, _appBarHeight = appBarHeight, @@ -39,6 +40,7 @@ class BrnAppBarConfig extends BrnBaseConfig { _titlePadding = titlePadding, _iconSize = iconSize, _systemUiOverlayStyle = systemUiOverlayStyle, + _showDefaultBottom = showDefaultBottom, super(configId: configId); BrnAppBarConfig.dark({ @@ -196,6 +198,14 @@ class BrnAppBarConfig extends BrnBaseConfig { _systemUiOverlayStyle ?? BrnDefaultConfigUtils.defaultAppBarConfig.systemUiOverlayStyle; + /// 是否展示Appbar bottom 分割线 + /// 默认为 [false] + bool? _showDefaultBottom; + + bool get showDefaultBottom => + _showDefaultBottom ?? + BrnDefaultConfigUtils.defaultAppBarConfig.showDefaultBottom; + @override void initThemeConfig( String configId, { @@ -222,6 +232,7 @@ class BrnAppBarConfig extends BrnBaseConfig { _titlePadding ??= appbarConfig._titlePadding; _iconSize ??= appbarConfig._iconSize; _systemUiOverlayStyle ??= appbarConfig._systemUiOverlayStyle; + _showDefaultBottom ??= appbarConfig._showDefaultBottom; } BrnAppBarConfig copyWith({ @@ -236,6 +247,7 @@ class BrnAppBarConfig extends BrnBaseConfig { EdgeInsets? titlePadding, double? iconSize, SystemUiOverlayStyle? systemUiOverlayStyle, + bool? showDefaultBottom, }) { return BrnAppBarConfig( backgroundColor: backgroundColor ?? _backgroundColor, @@ -249,6 +261,7 @@ class BrnAppBarConfig extends BrnBaseConfig { titlePadding: titlePadding ?? _titlePadding, iconSize: iconSize ?? _iconSize, systemUiOverlayStyle: systemUiOverlayStyle ?? _systemUiOverlayStyle, + showDefaultBottom: showDefaultBottom ?? _showDefaultBottom, ); } @@ -266,6 +279,7 @@ class BrnAppBarConfig extends BrnBaseConfig { titlePadding: other._titlePadding, iconSize: other._iconSize, systemUiOverlayStyle: other._systemUiOverlayStyle, + showDefaultBottom: other._showDefaultBottom, ); } } diff --git a/lib/src/theme/configs/brn_card_title_config.dart b/lib/src/theme/configs/brn_card_title_config.dart index 95ea6a70..2d95fa42 100644 --- a/lib/src/theme/configs/brn_card_title_config.dart +++ b/lib/src/theme/configs/brn_card_title_config.dart @@ -1,5 +1,5 @@ -import 'package:bruno/bruno.dart'; import 'package:bruno/src/theme/base/brn_base_config.dart'; +import 'package:bruno/src/theme/base/brn_default_config_utils.dart'; import 'package:bruno/src/theme/base/brn_text_style.dart'; import 'package:bruno/src/theme/brn_theme_configurator.dart'; import 'package:bruno/src/theme/configs/brn_common_config.dart'; diff --git a/lib/src/utils/brn_tools.dart b/lib/src/utils/brn_tools.dart index a5d90958..332d318c 100644 --- a/lib/src/utils/brn_tools.dart +++ b/lib/src/utils/brn_tools.dart @@ -124,7 +124,7 @@ class BrunoTools { return obj.isEmpty; } if (obj is Map) { - return obj.length == 0; + return obj.isEmpty; } return obj == null; } diff --git a/pubspec.yaml b/pubspec.yaml index 6ed0939a..bd8ceea0 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: bruno description: An enterprise-class package of Flutter components for mobile applications. -version: 2.1.1 +version: 2.2.0 homepage: https://github.com/LianjiaTech/bruno environment: @@ -21,6 +21,7 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter + lints: ^1.0.1