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: [
.........
],
),
)
);
},
);
}
}
2
Answers
In your
TabBar
, you need to notify the view when the tab changes, to rebuild the view again, try this:then you need to update you class to
StatefulWidget
, because you need to update your state.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
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());