afonsocraposo / buttons_tabbar

A Flutter package that implements a TabBar where each label is a toggle button.
https://pub.dev/documentation/buttons_tabbar/latest/
MIT License
103 stars 34 forks source link

Tab with badge or using custom widgets that do not inherit from `Tab` #24

Closed om-ha closed 2 years ago

om-ha commented 2 years ago

Hey there!

Great library you have here!

I would like more customization over the tab design. I was able to do everything I want with the parameters you provided, except for the tab badge.

Basically I want to show a badge on the top right corner.

There are two possible solutions for this:

om-ha commented 2 years ago

Could you please advise on how to do this? So I can just implement a workaround based on your suggestion.

om-ha commented 2 years ago

Resolved. I just used the child parameter of Tab object.

// 1. Map strings to tabs
var tabs = viewModel.myStringList
.mapIndexed( // import 'package:collection/collection.dart';
  (index, element) => MyTab(
    tabIndex: index,
    text: element,
  ),
)

// 2. ButtonsTabBar
ButtonsTabBar(
  height: 32,
  physics: const NeverScrollableScrollPhysics(), // scroll comes form parent `SingleChildScrollView`
  radius: 0, // no radius, `MyTab` manages this
  contentPadding: const EdgeInsets.only(), // no padding, `MyTab` manages this
  buttonMargin: const EdgeInsets.only(), // no margin, `MyTab` manages this
  backgroundColor: Colors.transparent, // no bg color, `MyTab` manages this
  unselectedBackgroundColor: Colors.transparent, // no bg color, `MyTab` manages this
  tabs: tabs,
  onTap: (int i) {
    pageControler.jumpToPage(i);
   myPageViewModel.tabIndexValueNotifier.value = i;
  },
),
om-ha commented 2 years ago

// 3. Wrapper type (you can remove this with some changes in code)

class MyTab extends Tab {
  MyTab({
    Key? key,
    required int tabIndex,
    required String text,
  }) : super(key: key, child: _MyTab(tabIndex: tabIndex, text: text));
}
om-ha commented 2 years ago

// 4. Custom tab type (this is where Tab.child design customization happens)

class _MyTab extends StatelessWidget {
  const _MyTab({
    Key? key,
    required this.tabIndex,
    required this.text,
  }) : super(key: key);

  final int tabIndex;
  final String text;

  @override
  Widget build(BuildContext context) {
    final myPageViewModel = getIt<MyPageViewModel>(); // courtesy of `get_it` https://pub.dev/packages/get_it
    return ValueListenableBuilder(
        valueListenable: myPageViewModel.tabIndexValueNotifier,
        builder: (context, value, child) {
          final isCurrentTab = tabIndex == value;
          final backgroundColor = isCurrentTab ? Colors.red.shade300 : Colors.black12;
          final showBadge = tabIndex > 0 && tabIndex < 3;

          return Stack(
            children: [
              Container(
                margin: const EdgeInsets.symmetric(horizontal: 4),
                padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16),
                decoration: BoxDecoration(
                  color: backgroundColor,
                  borderRadius: BorderRadius.circular(10),
                ),
                child: Text(text),
              ),
              PositionedDirectional(
                top: 0,
                end: 3.75,
                child: _MyTabBadge(
                  showBadge: showBadge,
                ),
              )
            ],
          );
        });
  }
}
om-ha commented 2 years ago

Enjoy!