diff --git a/example/lib/example_scaffold.dart b/example/lib/example_scaffold.dart index 73145ea..85c367c 100644 --- a/example/lib/example_scaffold.dart +++ b/example/lib/example_scaffold.dart @@ -8,11 +8,30 @@ class ExampleScaffold extends StatefulWidget { _ExampleScaffoldState createState() => _ExampleScaffoldState(); } -class _ExampleScaffoldState extends State { +class _ExampleScaffoldState extends State + with TickerProviderStateMixin { + TabController _tabController; + List tabs; + + @override + void initState() { + super.initState(); + tabs = List.generate(10, (index) => 'Tab $index'); + _tabController = TabController( + length: tabs.length, + vsync: this, + ); + } + @override Widget build(BuildContext context) { return ASScaffold( title: '标题', + appBarBottom: ASTabBar( + items: tabs, + isScrollable: true, + controller: _tabController, + ), ); } } diff --git a/lib/ansu_ui.dart b/lib/ansu_ui.dart index 07c84a5..c59dbd8 100644 --- a/lib/ansu_ui.dart +++ b/lib/ansu_ui.dart @@ -3,6 +3,7 @@ library ansu_ui; export 'buttons/as_button.dart'; export 'scaffold/as_scaffold.dart'; export 'styles/as_colors.dart'; +export 'tabbar/as_tabbar.dart'; //`BOTTOM` is external lib export 'package:flutter_screenutil/flutter_screenutil.dart'; diff --git a/lib/tabbar/as_tab_indicator.dart b/lib/tabbar/as_tab_indicator.dart new file mode 100644 index 0000000..bc03bdd --- /dev/null +++ b/lib/tabbar/as_tab_indicator.dart @@ -0,0 +1,84 @@ +import 'package:flutter/material.dart'; + +///渐变indicator +/// +///fork from TabIndicator +/// +///仅仅在发现页面中使用 +class ASTabIndicator extends Decoration { + const ASTabIndicator({ + this.borderSide = const BorderSide(width: 4.0, color: Colors.white), + this.insets = EdgeInsets.zero, + }) : assert(borderSide != null), + assert(insets != null); + + final BorderSide borderSide; + final EdgeInsetsGeometry insets; + + @override + Decoration lerpFrom(Decoration a, double t) { + if (a is ASTabIndicator) { + return ASTabIndicator( + borderSide: BorderSide.lerp(a.borderSide, borderSide, t), + insets: EdgeInsetsGeometry.lerp(a.insets, insets, t), + ); + } + return super.lerpFrom(a, t); + } + + @override + Decoration lerpTo(Decoration b, double t) { + if (b is ASTabIndicator) { + return ASTabIndicator( + borderSide: BorderSide.lerp(borderSide, b.borderSide, t), + insets: EdgeInsetsGeometry.lerp(insets, b.insets, t), + ); + } + return super.lerpTo(b, t); + } + + @override + _UnderlinePainter createBoxPainter([VoidCallback onChanged]) { + return _UnderlinePainter(this, onChanged); + } +} + +class _UnderlinePainter extends BoxPainter { + _UnderlinePainter(this.decoration, VoidCallback onChanged) + : assert(decoration != null), + super(onChanged); + + final ASTabIndicator decoration; + + BorderSide get borderSide => decoration.borderSide; + EdgeInsetsGeometry get insets => decoration.insets; + + Rect _indicatorRectFor(Rect rect, TextDirection textDirection) { + assert(rect != null); + assert(textDirection != null); + final Rect indicator = insets.resolve(textDirection).deflateRect(rect); + return Rect.fromLTWH( + indicator.left, + indicator.bottom - borderSide.width, + indicator.width, + borderSide.width, + ); + } + + @override + void paint(Canvas canvas, Offset offset, ImageConfiguration configuration) { + assert(configuration != null); + assert(configuration.size != null); + final Rect rect = offset & configuration.size; + final TextDirection textDirection = configuration.textDirection; + final Rect indicator = + _indicatorRectFor(rect, textDirection).deflate(borderSide.width / 2.0); + final Paint paint = borderSide.toPaint() + ..strokeCap = StrokeCap.square + ..shader = LinearGradient(colors: [ + Color(0xFFE50112), + Color(0xFFFFB1B1), + ]).createShader(rect); + canvas.drawLine(indicator.bottomLeft, indicator.bottomRight, paint); + } +} diff --git a/lib/tabbar/as_tabbar.dart b/lib/tabbar/as_tabbar.dart new file mode 100644 index 0000000..da8e891 --- /dev/null +++ b/lib/tabbar/as_tabbar.dart @@ -0,0 +1,46 @@ +import 'package:ansu_ui/styles/as_colors.dart'; +import 'package:ansu_ui/tabbar/as_tab_indicator.dart'; +import 'package:flutter/material.dart'; + +class ASTabBar extends StatefulWidget implements PreferredSizeWidget { + final List items; + final TabController controller; + + ///可滚动 + final bool isScrollable; + ASTabBar( + {Key key, + @required this.items, + @required this.controller, + this.isScrollable = false}) + : super(key: key); + + @override + _ASTabBarState createState() => _ASTabBarState(); + + @override + Size get preferredSize => Size.fromHeight(46); +} + +class _ASTabBarState extends State { + @override + Widget build(BuildContext context) { + return TabBar( + isScrollable: widget.isScrollable, + controller: widget.controller, + tabs: widget.items.map((e) => Tab(text: e)).toList(), + labelStyle: TextStyle( + fontSize: 14, + fontWeight: FontWeight.bold, + ), + unselectedLabelStyle: TextStyle( + fontWeight: FontWeight.normal, + ), + labelColor: kTextColor, + unselectedLabelColor: kTextSubColor, + indicatorSize: TabBarIndicatorSize.label, + indicatorPadding: EdgeInsets.zero, + indicator: ASTabIndicator(), + ); + } +}