Flutter Tab bar - How to assign diffrent color of each selected Tab?

Viewed 55
TabBar(
            controller: _tabController,
            unselectedLabelColor: Colors.grey,
            indicator: BoxDecoration(
              borderRadius: BorderRadius.circular(
                16.0,
              ),
              color: colors[_tabController.index],
            ),
            tabs: const [
              Tab(text: "INFO"),
              Tab(text: "ENGAGEMENT"),
              Tab(text: "TRACK"),
            ],
            labelStyle: const TextStyle(
                color: Colors.white,
                fontSize: 13,
                fontWeight: FontWeight.w600),
            unselectedLabelStyle: const TextStyle(
                color: Colors.grey,
                fontSize: 13,
                fontWeight: FontWeight.w600),
          ),
        ),
      ),

I wanted Each Tab to have a Different color when they're selected So I tried to change the color when the index changes by storing them in a list But it doesnt work without setState (I know its not changing the state because the color changes after quick reload)enter image description here

enter image description here

enter image description here

This is the expected output

2 Answers

You can include a listener on TabController and call setState there.

  _tabController = TabController(vsync: this, length: myTabs.length)
      ..addListener(() {
        setState(() {});
      });

The code below should do the trick. The missing part of your approach is a setState to refresh the screen with the current selected tab index. Check out the screen recording and the live demo on DartPad:

The TabBar do almost all the job already. Only the outside round border should be customized and it's just a matter of wrapping the TabBar into a Container. Containers are pretty easy to work with and highly customizable.

enter image description here

And here's the code itself as a minimal-reproducible-example:

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(),
      debugShowCheckedModeBanner: false,
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key}) : super(key: key);

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

const colors = [
  Color(0xFF64c636),
  Color(0xFFf2c32c),
  Color(0xFF00a9ce),
];

class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
  late TabController tabController;
  int _tabIndex = 0;
  @override
  void initState() {
    super.initState();
    tabController = TabController(length: 3, vsync: this)
      ..addListener(() {
        setState(() => _tabIndex = tabController.index);
      });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
        height: 48,
        margin: const EdgeInsets.all(12),
        decoration: BoxDecoration(
          borderRadius: const BorderRadius.all(Radius.circular(20)),
          border: Border.all(width: 2),
        ),
        child: TabBar(
          indicatorWeight: 0,
          controller: tabController,
          indicator: BoxDecoration(
              borderRadius: BorderRadius.circular(
                16.0,
              ),
              color: colors[_tabIndex],
            ),
          labelStyle: const TextStyle(
              color: Colors.white,
              fontSize: 13,
              fontWeight: FontWeight.w600),
          unselectedLabelColor: Colors.grey,
          splashBorderRadius: BorderRadius.circular(20),
          padding: EdgeInsets.all(3),
          tabs: const [
            Tab(text: 'INFO'),
            Tab(text: 'ENGAGEMENT'),
            Tab(text: 'TRACK'),
          ],
        ),
      ),
    );
  }
}
Related