I want to make a custom tab widget and set a list of this widgets to a tab bar. But tab bar can't take all space and some space will remain. I try to wrap it with PreferredSize but it doesn't work . The tab bar (ScrollTabBar) :
Widget build(BuildContext context) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Container(
decoration: BoxDecoration(
boxShadow: [
BoxShadow(
color: Colors.black54,
blurRadius: 5.0,
offset: Offset(0.0, 0.75),
),
],
borderRadius: BorderRadius.circular(widget.borderRadiusT),
color: Colors.red,
),
height: widget.tabHeight,
child: PreferredSize(
preferredSize: Size.fromHeight(widget.tabHeight),
child: TabBar(
indicator: UnderlineTabIndicator(
borderSide: BorderSide(
color: widget.indicatorColor,
width: widget.indicatorWheight,
),
insets: EdgeInsets.symmetric(
horizontal: widget.horizontalPadding,
),
),
indicatorWeight: widget.indicatorWheight,
indicatorColor: widget.indicatorColor,
labelPadding: EdgeInsets.only(
bottom: 0,
right: widget.horizontalPadding,
left: widget.horizontalPadding,
),
labelColor: widget.activeTextColor,
unselectedLabelColor: widget.diactiveTextColor,
controller: widget.tabController,
tabs: widget.tabList,
isScrollable: true,
),
),
),
Expanded(
child: TabBarView(
controller: widget.tabController,
children: [
for (var builder in widget.screenList) builder.call(context)
],
),
),
],
),
);
}
tabList is list of FTabComp :
FTabComp(
String title,
Key key,
ScrollTabBar parent, {
bool haveDivider = true,
}) {
return Tab(
key: key,
child: Container(
color: Colors.blue,
width: parent.tabLength,
child: Stack(
clipBehavior: Clip.none,
children: [
Align(
alignment: Alignment.center,
child: Text(title),
),
haveDivider
? Positioned.fill(
left: parent.tabLength * - 1.5,
child: SizedBox(
height: double.maxFinite,
child: VerticalDivider(
color: parent.outerBackgroundColor,
thickness: parent.dviderWidth,
),
),
)
: Center()
,
],
),
),
);
}
Container are red . Tabs are blue , if you solve this , I will say thank you.
Take a look on the changed code below:
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();
}
class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
late TabController tabController;
late TabController tabController2;
@override
void initState() {
// TODO: implement initState
super.initState();
tabController = TabController(length: 4, vsync: this);
tabController2 = TabController(length: 3, vsync: this);
}
@override
Widget build(BuildContext context) {
final tabCount = 4;
double horizontalPadding = 8;
return Scaffold(
body: ScrollTabBar(
tabController: tabController,
horizontalPadding: horizontalPadding,
tabList: [
FTabComp(
title: 'secKey',
key: ValueKey('tab1'),
outerBackgroundColor: Colors.black,
dviderWidth: 4,
tabCount: 4,
horizontalPadding: horizontalPadding,
),
FTabComp(
title: 'firstKey',
key: ValueKey('tab2'),
outerBackgroundColor: Colors.black,
dviderWidth: 4,
tabCount: 4,
horizontalPadding: horizontalPadding,
),
FTabComp(
title: 'otherKey',
key: ValueKey('tab3'),
outerBackgroundColor: Colors.black,
dviderWidth: 4,
tabCount: 4,
horizontalPadding: horizontalPadding,
),
FTabComp(
title: 'anotherKey',
key: ValueKey('tab4'),
outerBackgroundColor: Colors.black,
dviderWidth: 4,
tabCount: 4,
horizontalPadding: horizontalPadding,
),
],
screenList: [
(context) => const Text('Tab 1'),
(context) => const Text('Tab 2'),
(context) => const Text('Tab 3'),
(context) => const Text('Tab 4'),
],
),
);
}
}
class ScrollTabBar extends StatefulWidget {
double borderRadiusT;
double tabHeight;
Color indicatorColor;
Color activeTextColor;
Color diactiveTextColor;
double indicatorWheight;
double horizontalPadding;
Color outerBackgroundColor;
double dviderWidth;
final TabController? tabController;
final List<Widget> tabList;
final List<Widget Function(BuildContext)> screenList;
ScrollTabBar({
Key? key,
this.borderRadiusT = 4,
this.tabHeight = 48,
this.indicatorColor = Colors.blue,
this.activeTextColor = Colors.black,
this.diactiveTextColor = Colors.white38,
this.indicatorWheight = 8,
this.horizontalPadding = 8,
required this.tabController,
required this.tabList,
required this.screenList,
this.outerBackgroundColor = Colors.black,
this.dviderWidth = 4,
}) : super(key: key);
@override
State<ScrollTabBar> createState() => _ScrollTabBarState();
}
class _ScrollTabBarState extends State<ScrollTabBar> {
@override
Widget build(BuildContext context) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Container(
decoration: BoxDecoration(
boxShadow: [
BoxShadow(
color: Colors.black54,
blurRadius: 5.0,
offset: Offset(0.0, 0.75),
),
],
borderRadius: BorderRadius.circular(widget.borderRadiusT),
color: Colors.red,
),
height: widget.tabHeight,
child: TabBar(
indicator: UnderlineTabIndicator(
borderSide: BorderSide(
color: widget.indicatorColor,
width: widget.indicatorWheight,
),
insets: EdgeInsets.symmetric(
horizontal: widget.horizontalPadding,
),
),
indicatorWeight: widget.indicatorWheight,
indicatorColor: widget.indicatorColor,
labelPadding: EdgeInsets.only(
bottom: 0,
right: widget.horizontalPadding,
left: widget.horizontalPadding,
),
labelColor: widget.activeTextColor,
unselectedLabelColor: widget.diactiveTextColor,
controller: widget.tabController,
tabs: widget.tabList,
),
),
Expanded(
child: TabBarView(
controller: widget.tabController,
children: [
for (var builder in widget.screenList) builder.call(context)
],
),
),
],
),
);
}
}
class FTabComp extends StatelessWidget {
final String title;
final bool haveDivider;
final Color outerBackgroundColor;
final double dviderWidth;
final double horizontalPadding;
final int tabCount;
FTabComp({
Key? key,
required this.title,
this.haveDivider = true,
required this.outerBackgroundColor,
required this.dviderWidth,
required this.horizontalPadding,
required this.tabCount,
}) : super(key: key);
@override
Widget build(BuildContext context) {
double width = MediaQuery.of(context).size.width;
double tabLength = (width -
horizontalPadding * (tabCount 1) -
horizontalPadding * (tabCount - 1)) /
tabCount;
return Tab(
key: key,
child: Container(
color: Colors.blue,
child: Stack(
clipBehavior: Clip.none,
children: [
Align(
alignment: Alignment.center,
child: Text(title),
),
haveDivider
? Positioned.fill(
left: horizontalPadding tabLength - (dviderWidth / 2),
child: SizedBox(
height: double.maxFinite,
child: VerticalDivider(
color: outerBackgroundColor,
thickness: dviderWidth,
),
),
)
: Center(),
],
),
),
);
}
}