Flutter之TabBar篇

文章介绍了项目中使用的不同TabBar实现,包括系统自带的TabBar、基于buttons_tabbar第三方插件以及自定义的按钮容器。作者分享了代码示例,并表示会持续更新以适应新样式。
摘要由CSDN通过智能技术生成

总结了一下项目中用到的几种TabBar,针对不同的样式,有采用系统提供的,也有三方插件提供的,也有自定义的,效果如下(后续如果遇到新的样式,会不间断地记录更新,避免重复造轮子…)

请添加图片描述

用到的三方插件:

buttons_tabbar: ^1.3.8
flutter_easyloading: ^3.0.5

1、先看第一种系统的

在这里插入图片描述

代码如下:

class CustomTabBar extends StatelessWidget {
  final TabController tabController;
  final List<String> 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<String> _tabs = [
    "能源洞察",
    "用户故事",
    "智汇回答",
  ];
  final List<Widget> _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<String> _tabs = [
    "能源洞察",
    "用户故事",
    "智汇回答",
  ];
  final List<Widget> _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<int> 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<String> 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,
                );
              }),
            ),
代码已经都贴出来了,大方向已经指出标明,至于根据项目需求更改其中的细枝末节就需要自行动手了,有不懂的可以在下方留言,看到会及时回复😊
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值