Flutter之TabBar篇

总结了一下项目中用到的几种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,
                );
              }),
            ),
代码已经都贴出来了,大方向已经指出标明,至于根据项目需求更改其中的细枝末节就需要自行动手了,有不懂的可以在下方留言,看到会及时回复😊
相关推荐
恋猫de小郭1 小时前
Swift 6.3 正式发布支持 Android ,它能在跨平台发挥什么优势?
android·前端·flutter
i-阿松!5 小时前
PCB板子+ flutter前端 + go后端
物联网·flutter·pcb工艺·go1.19
恋猫de小郭5 小时前
Flutter 3.41.6 版本很重要,你大概率需要更新一下
android·前端·flutter
亚历克斯神16 小时前
Flutter for OpenHarmony: Flutter 三方库 mutex 为鸿蒙异步任务提供可靠的临界资源互斥锁(并发安全基石)
android·数据库·安全·flutter·华为·harmonyos
钛态17 小时前
Flutter 三方库 smartstruct 鸿蒙化字段映射适配指南:介入静态预编译引擎扫除视图及数据模型双向强转类型错乱隐患,筑稳如磐石的企业级模型治理防线-适配鸿蒙 HarmonyOS ohos
flutter·华为·harmonyos
键盘鼓手苏苏17 小时前
Flutter 组件 csv2json 适配鸿蒙 HarmonyOS 实战:高性能异构数据转换,构建 CSV 流式解析与全栈式数据映射架构
flutter·harmonyos·鸿蒙·openharmony
左手厨刀右手茼蒿17 小时前
Flutter 组件 http_requests 适配鸿蒙 HarmonyOS 实战:极简网络请求,构建边缘端轻量级 RESTful 通讯架构
网络·flutter·http
雷帝木木17 小时前
Flutter 三方库 hrk_logging 的鸿蒙化适配指南 - 实现标准化分层日志记录、支持多目的地输出与日志分级过滤
flutter·harmonyos·鸿蒙·openharmony·hrk_logging
左手厨刀右手茼蒿17 小时前
Flutter 三方库 dio_compatibility_layer 的鸿蒙化适配指南 - 实现 Dio 跨主版本的平滑迁移、支持遗留拦截器兼容与网络请求架构稳定升级
flutter·harmonyos·鸿蒙·openharmony·dio_compatibility_layer
雷帝木木17 小时前
Flutter 三方库 hashids2 基于鸿蒙安全内核的深度隐匿映射适配:数字指纹泄露防御层、生成短小精悍唯一不可逆加盐哈希,护航全链路请求 URL 隐私-适配鸿蒙 HarmonyOS ohos
安全·flutter·harmonyos