Reputation: 49
I want to be able to have the selected tab's underline within the tab bar to only be as long as the text for that tab (as shown below). I believe my issue is that I have a SizedBox
with a defined width
that uses the screen's width to determine the width of each tab. I did this since there would be a scroll with the "SHARE THE GOOD" tab as it's too long and I want all the tabs to fit on the screen with no scroll.
Here's the code I have for creating that tab bar
class HomeScreen extends StatelessWidget {
const HomeScreen({super.key});
static TextStyle tabTextStyle = smallCaps13;
@override
Widget build(BuildContext context) {
final double width = MediaQuery.of(context).size.width;
final List<Widget> tabs = [
SizedBox(
width: width * 0.25,
// padding: const EdgeInsets.symmetric(horizontal: 80.0),
child: const Tab(child: Text("HOME")),
),
SizedBox(
width: width * 0.25,
// padding: const EdgeInsets.symmetric(horizontal: 80.0),
child: const Tab(child: Text("NEWS")),
),
SizedBox(
width: width * 0.5,
// padding: const EdgeInsets.symmetric(horizontal: 80.0),
child: const Tab(child: Text("SHARE THE GOOD")),
),
];
return DefaultTabController(
length: tabs.length,
child: Column(
children: [
TabBar(
indicatorSize: TabBarIndicatorSize.label,
dividerColor: Colors.transparent,
splashFactory: NoSplash.splashFactory,
labelStyle: smallCaps13.copyWith(color: ftiDarkBlue),
unselectedLabelColor: ftiMediumGray,
tabAlignment: TabAlignment.start,
indicatorColor: Theme.of(context).colorScheme.secondary,
labelPadding: const EdgeInsets.symmetric(horizontal: 0),
isScrollable: true,
tabs: tabs,
),
const Expanded(
child: TabBarView(
children: [
HomeTab(),
NewsTab(),
ShareTheGoodTab(),
],
),
)
],
),
);
}
}
I tried adding indicatorSize: TabBarIndicatorSize.label,
to no avail as it's still considering that whole SizedBox
which makes sense.
Upvotes: 0
Views: 135
Reputation: 63769
You can have the default controller access like DefaultTabController.maybeOf(context)
but you need to go one level down to the context tree. I would say use a TabController.
The constraints left on your custom width of the TabBar item which isn't equal to the text. You can build it with Row, you can use Row/Column.
class HomeScreen extends StatefulWidget {
const HomeScreen({super.key});
static TextStyle tabTextStyle = const TextStyle();
@override
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen>
with SingleTickerProviderStateMixin {
late final tabController = TabController(length: 3, vsync: this);
@override
void dispose() {
tabController.dispose();
super.dispose();
}
final tabTitles = ["HomeTab", "News", "Share the good"];
@override
Widget build(BuildContext context) {
///
Widget _buildTab(int index, String text) {
return Expanded(
child: InkWell(
onTap: () {
tabController.animateTo(index);
setState(() {});
},
child: Tab(
child: DecoratedBox(
decoration: index == tabController.index
? const BoxDecoration(
border: Border(
bottom: BorderSide(
color: Colors.black,
width: 2.0,
),
),
)
: const BoxDecoration(),
child: Text(text, style: HomeScreen.tabTextStyle),
),
),
),
);
}
return Column(
children: [
Row(
children: [for (int i = 0; i < 3; i++) _buildTab(i, tabTitles[i])],
),
Expanded(
child: TabBarView(
controller: tabController,
children: [
Text("HOME"),
Text("NEWS"),
Text("SHARE THE GOOD"),
// HomeTab(),
// NewsTab(),
// ShareTheGoodTab(),
],
),
)
],
);
}
}
Upvotes: 1