Flutter之TabBar篇
总结了一下项目中用到的几种TabBar,针对不同的样式,有采用系统提供的,也有三方插件提供的,也有自定义的,效果如下(后续如果遇到新的样式,会不间断地记录更新,避免重复造轮子…)
用到的三方插件:
buttons_tabbar: ^1.3.8
flutter_easyloading: ^3.0.5
1、先看第一种系统的
代码如下:
class CustomTabBar extends StatelessWidget { final TabController tabController; final List tabs; final TextStyle labelStyle; final Color labelColor; final Color unselectedLabelColor; final TextStyle unselectedLabelStyle; final Color indicatorColor; final double indicatorWeight; const CustomTabBar({ super.key, required this.tabController, required this.tabs, this.labelStyle = const TextStyle( fontSize: 16.0, fontWeight: FontWeight.w700, ), this.labelColor = Colors.blue, this.unselectedLabelColor = Colors.red, this.unselectedLabelStyle = const TextStyle( fontSize: 16.0, fontWeight: FontWeight.w400, ), this.indicatorColor = Colors.blue, this.indicatorWeight = 5.0, }); @override Widget build(BuildContext context) { return TabBar( controller: tabController, tabs: tabs.map((e) => Tab(text: e)).toList(), isScrollable: true, labelPadding: const EdgeInsets.symmetric(horizontal: 16.0), labelStyle: labelStyle, labelColor: labelColor, unselectedLabelColor: unselectedLabelColor, unselectedLabelStyle: unselectedLabelStyle, indicatorWeight: indicatorWeight, indicator: DotTabIndicator( color: indicatorColor, radius: 4, ), onTap: (value) {}, dividerColor: Colors.transparent, //去除tabBar下面的那根线的颜色 ); } } class DotTabIndicator extends Decoration { final Color color; final double radius; const DotTabIndicator({required this.color, required this.radius}); @override BoxPainter createBoxPainter([VoidCallback? onChanged]) { return _DotTabIndicatorPainter(this, onChanged!); } } class _DotTabIndicatorPainter extends BoxPainter { final DotTabIndicator decoration; _DotTabIndicatorPainter(this.decoration, VoidCallback onChanged) : super(onChanged); @override void paint(Canvas canvas, Offset offset, ImageConfiguration configuration) { final Rect rect = offset & configuration.size!; final Paint paint = Paint(); paint.color = decoration.color; paint.style = PaintingStyle.fill; final Offset circleOffset = Offset(rect.center.dx, rect.bottomCenter.dy - decoration.radius); canvas.drawCircle(circleOffset, decoration.radius, paint); } }
使用方法:
late final TabController _tabController; final List _tabs = [ "能源洞察", "用户故事", "智汇回答", ]; final List _tabViews = [ Container(color: Colors.red), Container(color: Colors.yellow), Container(color: Colors.orange), ]; @override void initState() { super.initState(); _tabController = TabController( initialIndex: 1, length: _tabs.length, vsync: this, ); } @override void dispose() { _tabController.dispose(); super.dispose(); } Container( height: 200, child: Column( children: [ CustomTabBar( tabController: _tabController, indicatorWeight: 1, tabs: _tabs, ), const SizedBox(height: 10.0), Expanded( child: TabBarView( controller: _tabController, children: _tabViews, ), ), ], ), ),
第二种采用的三方插件buttons_tabbar: ^1.3.8
代码如下:
late final TabController _tabController; final List _tabs = [ "能源洞察", "用户故事", "智汇回答", ]; final List _tabViews = [ Container(color: Colors.red), Container(color: Colors.yellow), Container(color: Colors.orange), ]; @override void initState() { super.initState(); _tabController = TabController( initialIndex: 0, length: _tabs.length, vsync: this, ); } @override void dispose() { _tabController.dispose(); super.dispose(); } SizedBox( height: 200, child: Column( children: [ SizedBox( height: 32.0, child: ButtonsTabBar( tabs: _tabs.map((e) => Tab(text: e)).toList(), controller: _tabController, backgroundColor: Colors.blue, unselectedBackgroundColor: Colors.red, labelStyle: const TextStyle(color: Colors.white), unselectedLabelStyle: const TextStyle(color: Colors.black), buttonMargin: const EdgeInsets.only(right: 35), contentPadding: const EdgeInsets.symmetric(horizontal: 15.0), radius: 18, ), ), const SizedBox(height: 10.0), Expanded( child: TabBarView( controller: _tabController, children: _tabViews, ), ), ], ), ),
第三种自定义
代码如下:
class ButtonContainer extends StatelessWidget { final int containerIndex; final ValueChanged onContainerSelected; final bool isSelected; final List data; final Color backgroundColor; final Color unBackgroundColor; final TextStyle labelStyle; final TextStyle unLabelStyle; const ButtonContainer({ super.key, required this.containerIndex, required this.onContainerSelected, required this.isSelected, required this.data, this.backgroundColor = Colors.grey, this.unBackgroundColor = Colors.red, this.labelStyle = const TextStyle( color: Colors.black, fontSize: 16, ), this.unLabelStyle = const TextStyle( color: Colors.white, fontSize: 16, ), }); @override Widget build(BuildContext context) { return GestureDetector( onTap: () { onContainerSelected(containerIndex); }, child: Container( padding: const EdgeInsets.all(8.0), margin: const EdgeInsets.all(10), decoration: BoxDecoration( color: isSelected ? backgroundColor : unBackgroundColor, borderRadius: BorderRadius.circular(8.0), ), child: Text( data[containerIndex], style: isSelected ? labelStyle : unLabelStyle, ), ), ); } }
使用方法:
int selectedContainerIndex = 4; //默认选中第几个 final List dataList = [ "能源", "用户故事", "智回答", "能洞察", "用户故事", "智汇答", ]; Wrap( children: List.generate(dataList.length, (index) { return ButtonContainer( containerIndex: index, onContainerSelected: (index) { setState(() { // 更新选中状态 selectedContainerIndex = index; }); EasyLoading.showToast("Click---${dataList[index]}"); }, isSelected: index == selectedContainerIndex, data: dataList, ); }), ),
代码已经都贴出来了,大方向已经指出标明,至于根据项目需求更改其中的细枝末节就需要自行动手了,有不懂的可以在下方留言,看到会及时回复😊
免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理!
部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理!
图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!