Flutter创建TabBar

使用TabBar和TabBarView来创建一个包含"首页"、"分类"和"我的"的TabBar。每个Tab对应一个Tab控件,TabBarView中的每个页面对应一个Widget。

1.Tab使用自定义图标和颜色

一般UI设计的图会带渐变色之类的,应该保持图片的原状,不能随便就给改成纯色。

Dart 复制代码
import 'package:flutter/material.dart'; // 导入Flutter Material组件库

void main() {
  WidgetsFlutterBinding.ensureInitialized(); // 确保Flutter绑定到框架初始化
  runApp(const MyApp()); // 运行应用
}

class MyApp extends StatelessWidget {
  // 创建一个无状态的组件MyApp
  const MyApp({super.key}); // 构造函数,接收一个Key

  @override
  Widget build(BuildContext context) {
    // 重写build方法,构建UI
    return MaterialApp(
      debugShowCheckedModeBanner: false, // 禁用右上角的Debug标志
      theme: ThemeData(
        // 设置应用主题
        tabBarTheme: TabBarTheme(
          // 设置TabBar主题
          overlayColor: MaterialStateProperty.all<Color>(
              Colors.transparent), // 设置点击时的背景颜色为透明
        ),
      ),
      home: DefaultTabController(
        // 使用DefaultTabController来协调选项卡选择和内容显示
        initialIndex: 0, // 设置初始选中的Tab索引为0(首页)
        length: 3, // 设置Tab的数量
        child: Scaffold(
          // 创建一个Scaffold,提供基本的Material Design布局结构
          appBar: AppBar(
            // 创建一个AppBar
            title: const Text('My Flutter App'), // 设置AppBar的标题
          ), // 去掉顶部的导航栏,只需将appBar设置为null
          body: const TabBarView(
            // 创建TabBarView,用于显示Tab的内容
            physics:
                NeverScrollableScrollPhysics(), // 禁止在 TabBarView 中滑动切换选项卡,添加这行代码
            children: [
              Center(child: Text('首页:这里可以展示应用的主要内容')), // Tab 1 内容
              Center(child: Text('分类:这里可以展示商品或信息的分类')), // Tab 2 内容
              Center(child: Text('我的:这里可以展示用户的个人信息和设置')), // Tab 3 内容
            ],
          ),
          bottomNavigationBar: const TabBar(
            // 创建底部导航TabBar
            tabs: [
              // Tab项定义
              Tab(
                  icon: _TabIcon(
                      // 自定义Tab图标
                      activeIcon: // 选中状态的图标
                          AssetImage("assets/images/tab_home_selected.png"),
                      inactiveIcon: // 未选中状态的图标
                          AssetImage("assets/images/tab_home_default.png"),
                      index: 0), // Tab索引
                  text: "首页"), // Tab文本
              Tab(
                  icon: _TabIcon(
                      activeIcon:
                          AssetImage("assets/images/tab_category_selected.png"),
                      inactiveIcon:
                          AssetImage("assets/images/tab_category_default.png"),
                      index: 1),
                  text: "分类"),
              Tab(
                  icon: _TabIcon(
                      activeIcon:
                          AssetImage("assets/images/tab_mine_selected.png"),
                      inactiveIcon:
                          AssetImage("assets/images/tab_mine_default.png"),
                      index: 2),
                  text: "我的"),
            ],
            isScrollable: false, // 禁用滚动功能
            labelStyle: TextStyle(fontWeight: FontWeight.bold), // 设置文本样式为加粗
            labelColor: Colors.red, // 选项选中的颜色
            unselectedLabelColor: Colors.black, // 选项未选中的颜色
            indicatorColor: Colors.blue, // 下滑线颜色
            indicator: BoxDecoration(), // 设置为空的Container,隐藏下划线
          ),
        ),
      ),
    );
  }
}

class _TabIcon extends StatelessWidget {
  // 创建一个无状态的组件_TabIcon,用于显示Tab图标
  final AssetImage activeIcon; // 选中状态的图标
  final AssetImage inactiveIcon; // 未选中状态的图标
  final int index; // Tab索引

  const _TabIcon({
    // 构造函数
    Key? key,
    required this.activeIcon,
    required this.inactiveIcon,
    required this.index,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    // 重写build方法,构建UI
    final controller =
        DefaultTabController.of(context); // 获取当前上下文的DefaultTabController
    return ValueListenableBuilder(
      // 创建ValueListenableBuilder来监听变化
      valueListenable: controller.animation!, // 监听TabController的动画
      builder: (BuildContext context, value, Widget? child) {
        // 构建器回调
        final tabIndex = controller.index; // 获取当前选中的Tab索引
        return Image(
          // 创建Image组件来显示图标
          image:
              tabIndex == index ? activeIcon : inactiveIcon, // 根据Tab索引显示对应的图标
          width: 24, // 图标宽度
          height: 24, // 图标高度
        );
      },
    );
  }
}

这段代码创建了一个简单的Flutter应用,其中包含一个具有三个Tab的底部导航栏。每个Tab都有自己的图标和文本。这些Tab可以在用户点击它们时切换显示内容。代码中还包含了对Tab图标颜色的自定义处理,确保图标显示其原始颜色。

示意图:

2.Tab使用自定义图标,但不使用图标所带的颜色。

Dart 复制代码
import 'package:flutter/material.dart';

void main() {
  // 确保Flutter绑定到框架初始化
  WidgetsFlutterBinding.ensureInitialized();
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false, // 禁用右上角的Debug标志
      theme: ThemeData(
        tabBarTheme: TabBarTheme(
          overlayColor: MaterialStateProperty.all<Color>(
              Colors.transparent), // 设置点击时的背景颜色为透明
        ),
      ),
      home: DefaultTabController(
        length: 3,
        child: Scaffold(
          appBar: AppBar(
            title: const Text('My Flutter App'),
          ), // 去掉顶部的导航栏,只需将appBar设置为null
          body: const TabBarView(
            children: [
              Center(child: Text('首页:这里可以展示应用的主要内容')),
              Center(child: Text('分类:这里可以展示商品或信息的分类')),
              Center(child: Text('我的:这里可以展示用户的个人信息和设置')),
            ],
          ),
          bottomNavigationBar: const TabBar(
            tabs: [
              Tab(
                  icon: _TabIcon(
                      activeIcon:
                          AssetImage("assets/images/tab_home_selected.png"),
                      inactiveIcon:
                          AssetImage("assets/images/tab_home_default.png"),
                      index: 0),
                  text: "首页"),
              Tab(
                  icon: _TabIcon(
                      activeIcon:
                          AssetImage("assets/images/tab_category_selected.png"),
                      inactiveIcon:
                          AssetImage("assets/images/tab_category_default.png"),
                      index: 1),
                  text: "分类"),
              Tab(
                  icon: _TabIcon(
                      activeIcon:
                          AssetImage("assets/images/tab_mine_selected.png"),
                      inactiveIcon:
                          AssetImage("assets/images/tab_mine_default.png"),
                      index: 2),
                  text: "我的"),
            ],
            labelColor: Colors.red, // 选项选中的颜色
            unselectedLabelColor: Colors.grey, // 选项未选中的颜色

            indicatorColor: Colors.blue, // 下滑线颜色
            indicator: BoxDecoration(), // 设置为空的Container,隐藏下划线
          ),
        ),
      ),
    );
  }
}

class _TabIcon extends StatelessWidget {
  final AssetImage activeIcon;
  final AssetImage inactiveIcon;
  final int index;

  const _TabIcon({
    Key? key,
    required this.activeIcon,
    required this.inactiveIcon,
    required this.index,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final tabIndex = DefaultTabController.of(context).index;
    return ImageIcon(
      tabIndex == index ? activeIcon : inactiveIcon,
    );
  }
}

3.Tab使用系统图标

Dart 复制代码
import 'package:flutter/material.dart';

void main() {
  // 确保Flutter绑定到框架初始化
  WidgetsFlutterBinding.ensureInitialized();
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false, // 禁用右上角的Debug标志
      theme: ThemeData(
        tabBarTheme: TabBarTheme(
          overlayColor: MaterialStateProperty.all<Color>(
              Colors.transparent), // 设置点击时的背景颜色为透明
        ),
      ),
      home: DefaultTabController(
        length: 3,
        child: Scaffold(
          appBar: AppBar(
            title: const Text('My Flutter App'),
          ), // 去掉顶部的导航栏,只需将appBar设置为null
          body: const TabBarView(
            children: [
              Center(child: Text('首页:这里可以展示应用的主要内容')),
              Center(child: Text('分类:这里可以展示商品或信息的分类')),
              Center(child: Text('我的:这里可以展示用户的个人信息和设置')),
            ],
          ),
          bottomNavigationBar: const TabBar(
            tabs: [
              Tab(icon: Icon(Icons.home), text: "首页"),
              Tab(icon: Icon(Icons.category), text: "分类"),
              Tab(icon: Icon(Icons.person), text: "我的"),
            ],
            labelColor: Colors.red, // 选项选中的颜色
            unselectedLabelColor: Colors.grey, // 选项未选中的颜色

            indicatorColor: Colors.blue, // 下滑线颜色
            indicator: BoxDecoration(), // 设置为空的Container,隐藏下划线
          ),
        ),
      ),
    );
  }
}
相关推荐
梦想的颜色17 小时前
AI 时代小白 VibeCoding 做 APP:UniApp(含 Uni‑X)、Flutter 与 React Native+Expo全维度技术选型对比指南
flutter·react native·app·uniapp·vibecoding·unippx·app产品
坚果的博客20 小时前
Flutter-OH 3.44.9-dev 悄然上线|首个 OpenHarmony Canary 预览版上线
flutter
大龄秃头程序员21 小时前
Flutter 动画随笔:业务里真正高频的几类控件
flutter
天空之城--1 天前
Android Flutter行业最新动态与实用参考(2026年8月第2周)
android·flutter
恋猫de小郭1 天前
Flutter 3.47 发布,快来看看有什么更新吧
android·前端·flutter
大龄秃头程序员2 天前
一次 Flutter 动画 Demo 的整理与复盘
flutter
AlexMaybeBot2 天前
躺在沙发上开发 Openclaw 的移动端APP
前端·flutter
天空之城--2 天前
Android Flutter行业动态与学习参考(2026年8月)
android·flutter
FungLeo2 天前
Flutter Web token 存储陷阱:crypto.subtle 在非安全上下文失效排查实录
前端·安全·flutter
FungLeo2 天前
Flutter Web 中文字体困境与渲染器选择:CanvasKit vs HTML renderer 实战
前端·flutter·html