Home > Mobile >  Flutter : DefaultTabController Tabbar Tab Color not changing on selection
Flutter : DefaultTabController Tabbar Tab Color not changing on selection

Time:01-09

In my app I am using a DefaultTabController to display tabs which was working fine but i want to change the Tabbar Tab color when selecting a tab, which was not happening now. I used below code to highlight the selected tab color.

decoration: BoxDecoration(color: tabController?.index == 0 ? highlightColor : normalColor,border: Border.all(color: level1Color6,width: 2,style: BorderStyle.solid),borderRadius: BorderRadius.circular(5)),
            

Below is my complete code :

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

@override
void initState() {
    initState();
}

@override
void dispose() {
    dispose();
}

@override
Widget build(BuildContext context) {
    final screenWidth = getScreenWidth(context);
    final screenHeight = getScreenHeight(context);
    TabController? tabController;

    PreferredSizeWidget sizedAppBar = AppBar(
      title: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
           .....
        ],
      ),
      bottom: PreferredSize(
        preferredSize: Size.fromHeight(50.0),
        child: Container(
        alignment: Alignment.centerLeft,
        padding: EdgeInsets.symmetric(horizontal: 20),
        child: Column(
            mainAxisAlignment: MainAxisAlignment.start,
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
                  .....
            ],
        ),
        ),
      ),
    );

    PreferredSizeWidget sizedTabBar = TabBar(
        controller: tabController,
        labelColor: textWhite1,
        unselectedLabelColor: Colors.black,
        indicatorWeight: 2,
        isScrollable: true,
        indicatorSize: TabBarIndicatorSize.tab,
        indicatorColor: highlightColor,
        indicatorPadding: EdgeInsets.only(left: 2.0, right: 2.0,bottom: 3.0),
        indicator: BoxDecoration(
            borderRadius: BorderRadius.circular(5), // Creates border
            color: highlightColor,
            shape: BoxShape.rectangle,

        ),
        labelPadding: EdgeInsets.symmetric (horizontal: 1),
        tabs: [
            Container(
            width: mainTabWidth,
            height: mainTabHeight,
            decoration: BoxDecoration(color: tabController?.index == 0 ? highlightColor : normalColor,border: Border.all(color: level1Color6,width: 2,style: BorderStyle.solid),borderRadius: BorderRadius.circular(5)),
            child: Tab(child:Text(tab1,textAlign: TextAlign.center,style: TextStyle(fontSize: fontSize,fontWeight: FontWeight.bold,),),),
            ),
            Container(
            width: mainTabWidth,
            height: mainTabHeight,
            decoration: BoxDecoration(color: tabController?.index == 1 ? highlightColor : normalColor,border: Border.all(color: level1Color6,width: 2,style: BorderStyle.solid),borderRadius: BorderRadius.circular(5)),
            child: Tab(child:Text(tab2,textAlign: TextAlign.center,style: TextStyle(fontSize: fontSize,fontWeight: FontWeight.bold,),),),
            ),
            Container(
            width: mainTabWidth,
            height: mainTabHeight,
            decoration: BoxDecoration(color: tabController?.index == 2 ? highlightColor : normalColor,border: Border.all(color: level1Color6,width: 2,style: BorderStyle.solid),borderRadius: BorderRadius.circular(5)),
            child: Tab(child:Text(tab3,textAlign: TextAlign.center,style: TextStyle(fontSize: fontSize,fontWeight: FontWeight.bold,),),),
            ),
            Container(
            width: mainTabWidth,
            height: mainTabHeight,
            decoration: BoxDecoration(color: tabController?.index == 3 ? highlightColor : normalColor,border: Border.all(color: level1Color6,width: 2,style: BorderStyle.solid),borderRadius: BorderRadius.circular(5)),
            child: Tab(child:Text(tab4,textAlign: TextAlign.center,style: TextStyle(fontSize: fontSize,fontWeight: FontWeight.bold,),),),
            ),
        ],
    );

    final mediaQuery = MediaQuery.of(context);
    final availableHeight = screenHeight - sizedAppBar.preferredSize.height - sizedTabBar.preferredSize.height - mediaQuery.padding.top;

    return MultiBlocProvider(
        providers: [
            BlocProvider(
            create: (context) => TabBloc()..add(TabInitialEvent()),
            )
        ],
        child: MaterialApp(
            scrollBehavior: MyCustomScrollBehavior(),
            title: 'Tab Home',
            debugShowCheckedModeBanner: false,
            home: Scaffold(
            appBar: sizedAppBar,
            body: SafeArea(
                child: Column(
                    children: [
                    SizedBox(height: 3,),
                    DefaultTabController(
                        length: 4, // length of tabs
                        initialIndex: 0,
                        child: Builder(
                            builder: (context) {
                            tabController = DefaultTabController.of(context);
                            tabController?.addListener(() {
                                print("New tab index: ${tabController?.index}");
                            });
                            return Column(
                                    children: <Widget>[
                                    Container(
                                        child: sizedTabBar,
                                    ),
                                    //SizedBox(height: 1.0),
                                    Container(
                                        height: availableHeight * 0.93, //height of TabBarView
                                        decoration: BoxDecoration(
                                            border: Border(top: BorderSide(color: Colors.grey, width: 0.5))
                                        ),
                                        child: TabBarView(
                                        controller: tabController,
                                        children: <Widget>[
                                            Container(
                                            child: Column(
                                                children: [
                                                getFirstTab(screenWidth,screenHeight),
                                                ],
                                            ),
                                            ),
                                            Container(
                                            child: Center(
                                                child: Text('Display Tab 2', style: TextStyle(fontSize: 22, fontWeight: FontWeight.bold)),
                                            ),
                                            ),
                                            Container(
                                            child: Center(
                                                child: ElevatedButton(
                                                    child: Text('to Tab 3'),
                                                    onPressed: () {
                                                    print('Tab Now ${tabController?.index}');
                                                    tabController?.animateTo(1);
                                                    }
                                                ),
                                            ),
                                            ),
                                            Container(
                                            child: Center(
                                                child: Text('Display Tab 4', style: TextStyle(fontSize: 22, fontWeight: FontWeight.bold)),
                                            ),
                                            ),
                                        ],
                                        ),
                                    ),
                                    ],);
                            }
                        )
                    ),
                    ],
                )
            ),
            ),
        ),
        );
    }

    getFirstTab(double screenWidth, double screenHeight) {
        return BlocBuilder<TabBloc, TabState>(
        builder: (context, state) {
            return Expanded(
                child: Scrollbar(
                controller: controller,
                child: ListView(
                    controller: controller,
                    shrinkWrap: true,
                    children: [
                       .........
                    ],
                ),
                )
            );
        },
        );
    }
}

CodePudding user response:

In your TabBar, you need to notify the view when the tab changes, to rebuild the view again, try this:

PreferredSizeWidget sizedTabBar = TabBar(
     onTap: (_){
        setState(() {});
     },
     ...
)

then you need to update you class to StatefulWidget, because you need to update your state.

CodePudding user response:

You have to options to do so.

The first: is to use stateful widget instead of stateless widget so you can update the current page state using

setState((){});

The second: is to use one of the state management like getX, Provider, Bloc .. etc.

this will help you with bigger projects even if you're using stateless widget you can update your current state so you can make changes to your screen while using Bloc you can do emit(YourStateHere());

  • Related