user14709104
user14709104

Reputation:

Customize tab bar inside SliverPersistantHeader flutter

I need a tab bar with the following effect:

enter image description here

Right now my code stands at:

              SliverPersistentHeader(
              pinned: true,
              delegate: SliverAppBarDelegate(
                TabBar(
                  isScrollable: true,
                  indicatorSize: TabBarIndicatorSize.tab,
                  indicator: BoxDecoration(
                    gradient: LinearGradient(
                    colors: [Colors.white70, Colors.grey],
                  ),
                  borderRadius: BorderRadius.circular(20),
                    color: Colors.red,
                  ),
                  labelColor: CustomColors.primary,
                  unselectedLabelColor: CustomColors.secondary,
                  tabs: categories
                      .map((category) => Tab(
                            text: category,
                          ))
                      .toList(),
                  controller: _tabController,
                ),
              ),
            ),

And the delegate:

class SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
  SliverAppBarDelegate(this._tabBar);

  final TabBar _tabBar;

  @override
  double get minExtent => _tabBar.preferredSize.height;

  @override
  double get maxExtent => _tabBar.preferredSize.height;

  @override
  Widget build(
      BuildContext context, double shrinkOffset, bool overlapsContent) {
    return new Container(
      height: 80,
      color: CustomColors.white,
      child: _tabBar,
    );
  }

  @override
  bool shouldRebuild(SliverAppBarDelegate oldDelegate) {
    return false;
  }
}

The current tab bar "tabs" are on default height. How can I achieve the same as the picture?

N.B: The SliverAppBarDelegate is in a separate file. Is it possible to move the TabBar() to another file as well?

Upvotes: 0

Views: 383

Answers (1)

This maybe works for you

tabController.index get the current index of the tab then you can decide what behavior show in any case

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

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

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
  List<String> categories = [
    'All',
    'Food',
    'Drink',
    'Clothes',
    'Electronics',
    'Others'
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      body: DefaultTabController(
          length: categories.length,
          child: Builder(builder: (BuildContext context) {
            final TabController tabController =
                DefaultTabController.of(context)!;
            tabController.addListener(() {
              if (!tabController.indexIsChanging) {
                int index = tabController.index;
                setState(() {});
                // Your code goes here.
                // To get index of current tab use tabController.index
              }
            });
            return Scaffold(
              extendBodyBehindAppBar: true,
              appBar: AppBar(
                shape: const Border(
                  bottom: BorderSide(color: Colors.black12, width: 1),
                ),
                backgroundColor: Colors.transparent,
                elevation: 0,
                bottom: TabBar(
                  labelColor: Colors.white,
                  indicatorColor: Colors.transparent,
                  isScrollable: true,
                  padding: const EdgeInsets.all(3),
                  tabs: categories
                      .map(
                        (category) => Tab(
                          icon: Container(
                            width: MediaQuery.of(context).size.width * 0.3,
                            height: MediaQuery.of(context).size.height * 0.06,
                            decoration: tabController.index ==
                                    categories.indexOf(category)
                                ? BoxDecoration(
                                    color: Colors.white,
                                    borderRadius: BorderRadius.circular(10),
                                    boxShadow: const [
                                      BoxShadow(
                                        color: Colors.black12,
                                        blurRadius: 10,
                                        // offset: Offset(3, 6),
                                      )
                                    ],
                                  )
                                : const BoxDecoration(),
                            child: Row(
                              mainAxisAlignment: MainAxisAlignment.center,
                              children: [
                                const Icon(
                                  Icons.ac_unit,
                                  color: Colors.black54,
                                ),
                                Text(
                                  category,
                                  style: const TextStyle(
                                    color: Colors.black54,
                                    fontSize: 18,
                                  ),
                                )
                              ],
                            ),
                          ),
                        ),
                      )
                      .toList(),
                ),
              ),
              body: TabBarView(
                controller: tabController,
                children: const [
                  Center(child: Text('All')),
                  Center(child: Text('Food')),
                  Center(child: Text('Drink')),
                  Center(child: Text('Clothes')),
                  Center(child: Text('Electronics')),
                  Center(child: Text('Others')),
                ],
              ),
            );
          })),
    );
  }
}

looks like enter image description here

Upvotes: 1

Related Questions