You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter教程:如何在TabBarView中创建自定义标签页?

Flutter TabBar 实现选中/未选中标签背景色切换解决方案

你的核心问题是给每个Tab内部的Container设置了固定灰色背景,导致TabBar的indicator被完全遮挡,而且无法动态切换选中状态的背景色。下面是修复后的完整实现:

完整代码实现

import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';

class CustomTabBarPage extends StatefulWidget {
  const CustomTabBarPage({super.key});

  @override
  State<CustomTabBarPage> createState() => _CustomTabBarPageState();
}

class _CustomTabBarPageState extends State<CustomTabBarPage> with SingleTickerProviderStateMixin {
  late TabController _tabController;
  int _selectedIndex = 0;

  @override
  void initState() {
    super.initState();
    _tabController = TabController(length: 4, vsync: this, initialIndex: 0);
    // 监听标签切换事件,更新选中索引
    _tabController.addListener(() {
      if (_tabController.indexIsChanging) {
        setState(() {
          _selectedIndex = _tabController.index;
        });
      }
    });
  }

  @override
  void dispose() {
    _tabController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: [
          TabBar(
            controller: _tabController,
            isScrollable: true,
            labelColor: Colors.black,
            unselectedLabelColor: Colors.black,
            labelPadding: const EdgeInsets.only(left: 8, right: 5),
            // 移除原来的indicator,因为背景色直接在Tab内部控制
            indicator: const BoxDecoration(),
            tabs: [
              // 第一个标签
              _buildTab('Featured', const Icon(Icons.favorite, color: Color(0xffef5145)), 0),
              // 第二个标签(示例)
              _buildTab('Latest', const Icon(Icons.access_time, color: Colors.grey), 1),
              // 第三个标签(示例)
              _buildTab('Popular', const Icon(Icons.trending_up, color: Colors.blue), 2),
              // 第四个标签(示例)
              _buildTab('Saved', const Icon(Icons.bookmark, color: Colors.orange), 3),
            ],
          ),
          Expanded(
            child: TabBarView(
              controller: _tabController,
              children: const [
                Center(child: Text('Featured Tab Content')),
                Center(child: Text('Latest Tab Content')),
                Center(child: Text('Popular Tab Content')),
                Center(child: Text('Saved Tab Content')),
              ],
            ),
          ),
        ],
      ),
    );
  }

  // 封装标签构建方法,复用代码
  Widget _buildTab(String title, Icon icon, int index) {
    return Tab(
      child: Container(
        decoration: BoxDecoration(
          borderRadius: BorderRadius.circular(10),
          // 动态设置背景色:选中时蓝色,未选中时灰色
          color: _selectedIndex == index ? const Color(0xff42a5f5) : const Color(0xfff4f4f4),
        ),
        height: 40,
        width: 110,
        child: Row(
          children: [
            Padding(
              padding: const EdgeInsets.only(left: 8),
              child: Text(
                title,
                style: GoogleFonts.poppins(
                  fontWeight: FontWeight.w700,
                  fontSize: 15,
                  letterSpacing: 0.3,
                ),
              ),
            ),
            Padding(
              padding: const EdgeInsets.only(left: 1),
              child: icon,
            ),
          ],
        ),
      ),
    );
  }
}

关键修复点说明

  • 移除固定背景色:删掉每个Tab内部Container的固定color,改为根据选中状态动态赋值
  • 使用StatefulWidget+TabController:通过监听TabController的切换事件,更新选中索引状态
  • 封装标签构建方法:避免重复代码,统一管理标签的样式逻辑
  • 隐藏默认indicator:因为背景色直接在Tab容器中控制,不需要默认的indicator,避免视觉重叠

这样就能实现你要的效果:未选中标签显示灰色#f4f4f4,选中时切换为蓝色#42a5f5,点击标签时自动切换背景色。

内容的提问来源于stack exchange,提问作者Divya

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 19:33:19