sliver_tabbar_with_mixed_list 1.0.1 copy "sliver_tabbar_with_mixed_list: ^1.0.1" to clipboard
sliver_tabbar_with_mixed_list: ^1.0.1 copied to clipboard

A sliver with a pinned button tab bar over sections that may nest and mix row heights. The tab bar follows the scroll position.

SliverTabBarWithMixedList #

Pub Version License: MIT pub points likes

A sliver with a pinned pill tab bar over a list of sections. Sections may nest, rows may have different heights, and the tab bar follows the scroll position — tapping a tab scrolls to its section.

https://github.com/Bomsamdi/sliver_tabbar_with_mixed_list/assets/94292009/0c8626a6-7e46-4213-b11b-427ad4536e55

Installation #

dependencies:
  sliver_tabbar_with_mixed_list: ^1.0.0

Requires Dart 3.8 / Flutter 3.32 or newer.

Usage #

Describe the rows by extending HeaderItem, SubheaderItem, ChildItem and VariantChildItem. Every row carries its own itemHeight; section offsets are computed from those, so there is no offset arithmetic to get right.

class Course extends HeaderItem {
  const Course({
    required super.key,
    required this.name,
    required super.tabLabel,
    super.children,
    super.subSections,
  }) : super(itemHeight: 64);
  final String name;
}

class Dish extends ChildItem {
  const Dish({required super.key, required this.name}) : super(itemHeight: 72);
  final String name;
}

CustomScrollView(
  controller: _controller,
  slivers: <Widget>[
    const SliverAppBar(pinned: true, title: Text('Menu')),
    SliverTabBarWithMixedList(
      controller: _controller,
      listItemHeight: 72,
      sections: sections,
      headerBuilder: (context, item) => Text((item as Course).name),
      childBuilder: (context, item) => Text((item as Dish).name),
      onSectionChanged: (index) => setState(() => _section = index),
    ),
  ],
)

The controller must be the one the enclosing CustomScrollView uses.

Nested sections and mixed heights #

HeaderItem.subSections nests sections; a VariantChildItem is drawn by variantChildBuilder and may be taller than the ordinary rows. Only top level sections get a tab.

Custom tabs #

tabLabel names the default tab. generateTabs replaces them entirely:

generateTabs: (List<HeaderItem> sections) => <TabItem>[
  for (int i = 0; i < sections.length; i++)
    TabItem(key: ValueKey<int>(i), headerItem: sections[i], text: 'Tab $i'),
],

Parameters #

Parameter Default Description
sections required Top level sections.
listItemHeight required Fallback row height when an item reports none.
controller required The enclosing scroll view's controller.
childBuilder required Builds an ordinary row.
headerBuilder, subHeaderBuilder, variantChildBuilder null Builders for the other row kinds.
generateTabs null Builds the tabs; defaults to one per section from tabLabel.
onSectionChanged null Called with the section index on every change.
scrollAnimated / scrollDuration true / 300 ms Tab tap scrolling.
startOffset 0 Extent of the slivers above this one.
customFooterWidget / footerHeight null Space under a short last section.
isTabBarVisible true Hides the tab bar entirely.
tabBarButtonBackgroundColor, tabBarButtonUnselectedBackgroundColor, tabBarButtonRadius theme / 24 The pill look.
labelStyle, unselectedLabelStyle theme Tab label styles.
tabBarIndicator null Takes over the selected look from the pill.
prefixWidget, sufixWidget null Widgets beside the tab bar.
tabBarPadding, buttonMargin, contentPadding zero / 4 / zero Spacing.
itemExtentBuilder null Overrides the row extent; must agree with itemHeight.

Migrating from 0.0.9 #

  • Offsets are computed for you. offsetStart, childrenCount and childrenHeight on HeaderItem are deprecated and ignored — delete the arithmetic. Getting it right by hand across nested, mixed-height sections was impractical; the package's own example had it wrong, so tapping a tab landed on the wrong section.
  • childrean is now children. The old name still works and is deprecated.
  • generateTabs, the tab colours and the label styles are optional now, defaulting to the ambient ColorScheme.
  • The buttons_tabbar dependency is gone, replaced by the framework's TabBar. That package left a pending timer behind and threw a _TypeError when it was removed from the widget tree, which took the screen down on navigation.
  • Section, SubSection, HeaderItem.params and iterateSections were unused scaffolding and have been removed.

License #

MIT.

1
likes
160
points
152
downloads

Documentation

API reference

Publisher

verified publisherbomsamdi.com

Weekly Downloads

A sliver with a pinned button tab bar over sections that may nest and mix row heights. The tab bar follows the scroll position.

Repository (GitHub)
View/report issues

Topics

#sliver #tabs #list #scrolling #widget

License

MIT (license)

Dependencies

after_first_frame_mixin, flutter, sliver_tools

More

Packages that depend on sliver_tabbar_with_mixed_list