diff --git a/example/lib/example_tab_bar.dart b/example/lib/example_tab_bar.dart index 18aabd6..50fb705 100644 --- a/example/lib/example_tab_bar.dart +++ b/example/lib/example_tab_bar.dart @@ -13,12 +13,14 @@ class _ExampleTabBarState extends State TabController _tabController1; TabController _tabController2; TabController _tabController3; + TabController _tabController4; @override void initState() { super.initState(); _tabController1 = TabController(length: 3, vsync: this); _tabController2 = TabController(length: 5, vsync: this); _tabController3 = TabController(length: 10, vsync: this); + _tabController4 = TabController(length: 10, vsync: this); } @override @@ -26,6 +28,7 @@ class _ExampleTabBarState extends State _tabController1?.dispose(); _tabController2?.dispose(); _tabController3?.dispose(); + _tabController4?.dispose(); super.dispose(); } @@ -33,8 +36,10 @@ class _ExampleTabBarState extends State Widget build(BuildContext context) { return ASScaffold( title: '选项卡 TabBar', - appBarBottom: PreferredSize( + body: Material( + color: kForegroundColor, child: Column( + mainAxisSize: MainAxisSize.min, children: [ ASTabBar( items: ['全部', 'Part1', 'Part2'], @@ -49,9 +54,15 @@ class _ExampleTabBarState extends State items: List.generate(10, (index) => 'Tab $index'), controller: _tabController3, ), + ASTabBar.tag( + isScrollable: true, + tabItems: List.generate(10, (index) => 'Tab $index') + .map((e) => ASTabBarItem(title: e, tag: e)) + .toList(), + controller: _tabController4, + ), ], ), - preferredSize: Size.fromHeight(46 * 3.0), ), ); } diff --git a/lib/ansu_ui.dart b/lib/ansu_ui.dart index 29d0efd..032eba2 100644 --- a/lib/ansu_ui.dart +++ b/lib/ansu_ui.dart @@ -20,6 +20,7 @@ export 'scaffold/as_scaffold.dart'; export 'styles/as_colors.dart'; export 'bar/as_tabbar.dart'; +export 'bar/as_tabbar_item.dart'; export 'bar/as_navigation_bar.dart'; export 'bar/as_navigation_item.dart'; @@ -54,6 +55,7 @@ export 'pop_up_menu/pop_up_menu.dart'; export 'tag/as_tag.dart'; export 'divider/as_divider.dart'; export 'text_field/as_search_text_field.dart'; +export 'badge/as_badge.dart'; export 'utils/screen_adapter.dart'; export 'utils/camera_util.dart'; diff --git a/lib/badge/as_badge.dart b/lib/badge/as_badge.dart new file mode 100644 index 0000000..a20e809 --- /dev/null +++ b/lib/badge/as_badge.dart @@ -0,0 +1,46 @@ +import 'package:flutter/material.dart'; +import 'package:ansu_ui/extension/string_extension.dart'; +import 'package:ansu_ui/extension/text_extension.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:ansu_ui/extension/num_extension.dart'; + +class ASBadge extends StatelessWidget { + final Widget child; + final String tag; + const ASBadge({Key key, @required this.child, this.tag}) + : assert(child != null), + super(key: key); + + @override + Widget build(BuildContext context) { + return (tag?.length ?? 0) == 0 + ? child + : Stack( + overflow: Overflow.visible, + children: [ + child, + Positioned( + right: -16.w, + top: -8.w, + child: Container( + constraints: BoxConstraints(minWidth: 16.w), + alignment: Alignment.center, + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [ + Color(0xFFE70F1F), + Color(0xFFFF98A8), + ], + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + ), + borderRadius: 8.radius, + ), + height: 16.w, + child: '12'.text.white.size(10), + ), + ), + ], + ); + } +} diff --git a/lib/bar/as_tabbar.dart b/lib/bar/as_tabbar.dart index fcf37aa..d6e2adb 100644 --- a/lib/bar/as_tabbar.dart +++ b/lib/bar/as_tabbar.dart @@ -1,6 +1,9 @@ +import 'package:ansu_ui/badge/as_badge.dart'; import 'package:ansu_ui/bar/as_tab_indicator.dart'; +import 'package:ansu_ui/bar/as_tabbar_item.dart'; import 'package:flutter/material.dart'; import 'package:ansu_ui/styles/as_colors.dart'; +import 'package:ansu_ui/extension/string_extension.dart'; /// ## 安速Tabbar /// @@ -11,6 +14,8 @@ class ASTabBar extends StatefulWidget implements PreferredSizeWidget { ///items final List items; + final List tabItems; + /// TabController final TabController controller; @@ -21,7 +26,16 @@ class ASTabBar extends StatefulWidget implements PreferredSizeWidget { @required this.items, @required this.controller, this.isScrollable = false}) - : super(key: key); + : tabItems = null, + super(key: key); + + ASTabBar.tag( + {Key key, + @required this.tabItems, + @required this.controller, + this.isScrollable = false}) + : items = null, + super(key: key); @override _ASTabBarState createState() => _ASTabBarState(); @@ -31,6 +45,7 @@ class ASTabBar extends StatefulWidget implements PreferredSizeWidget { } class _ASTabBarState extends State { + bool get isTag => widget.items?.isEmpty ?? true; @override Widget build(BuildContext context) { return Align( @@ -38,7 +53,20 @@ class _ASTabBarState extends State { child: TabBar( isScrollable: widget.isScrollable, controller: widget.controller, - tabs: widget.items.map((e) => Tab(text: e)).toList(), + tabs: isTag + ? widget.tabItems.map((e) { + return Tab( + child: ASBadge( + child: e.title.text, + tag: e.tag, + ), + ); + }).toList() + : widget.items + .map((e) => Tab( + child: e.text, + )) + .toList(), labelStyle: TextStyle( fontSize: 14, fontWeight: FontWeight.bold, diff --git a/lib/bar/as_tabbar_item.dart b/lib/bar/as_tabbar_item.dart new file mode 100644 index 0000000..f89ac89 --- /dev/null +++ b/lib/bar/as_tabbar_item.dart @@ -0,0 +1,8 @@ +class ASTabBarItem { + String title; + String tag; + ASTabBarItem({ + this.title, + this.tag, + }); +} diff --git a/pubspec.yaml b/pubspec.yaml index a1a46e7..2580d73 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -15,7 +15,7 @@ dependencies: lpinyin: ^1.1.0 image_picker: ^0.6.7+15 bot_toast: ^3.0.5 - + dev_dependencies: flutter_test: sdk: flutter