Home > Enterprise >  Flutter Tab bar can't take all space
Flutter Tab bar can't take all space

Time:06-29

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. Small width Medium width Large width

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(),
          ],
        ),
      ),
    );
  }
}
  • Related