Skip to main content

tab_overview 0.2.10 copy "tab_overview: ^0.2.10" to clipboard
tab_overview: ^0.2.10 copied to clipboard

Tab switcher with live thumbnails: show the tabs your app keeps open in a grid, zoom one into a full page, swipe between pages, drag to reorder and swipe to close.

example/example.md

Flutter tab switcher example

This Flutter tab switcher example opens five numbered tabs as live thumbnails in a grid: tap one, and it zooms into its page. Swipe to the next page, or pull the page down to zoom back out. Drag a thumbnail to reorder the tabs, swipe it away or tap its close button to close it, and tap + to add a tab.1

See the code › Install tab_overview ›

Flutter tab switcher example: a tap zooms a thumbnail into its page, a swipe turns to the next one, and a pull down zooms back out to the grid; + adds a tab, a drag takes it to the front, and a swipe closes it

Get the highlights. #

  • Live thumbnails. Each thumbnail is the tab's own page, scaled down to its cell, so it shows what the page shows.
  • Zoom in and out. A tap zooms a thumbnail into its page, and the page back out, with a hero animation within the same page. A pull down zooms a page out too.
  • Swipe between pages. An open tab is one page of many: swipe sideways to the next tab.
  • Drag to reorder. A long press lifts a thumbnail, and the others slide out of its way as it moves.
  • Close and add. A swipe or the close button closes a tab, and + adds one, as the grid closes the gap or makes room.

Take a closer look. #

Three steps, all in one build method:

  1. The controller. A TabOverviewController holds the tabs, numbered 1 to 5, and whether they show as a grid of thumbnails or as pages.
  2. The tab switcher. TabOverview.builder builds each tab's page with tabBuilder. The grid shows the same page, scaled down, as the tab's thumbnail, and pullToCollapse lets a pull down zoom a page back out.
  3. The changes. A tap on a thumbnail calls expand, and a tap on a page collapse. The buttons call toggleMode, remove and add, and the tab switcher animates each change.
import 'dart:math';

import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:tab_overview/tab_overview.dart';

import 'style/style.dart';
import 'tab_page.dart';

void main() => runApp(
  MaterialApp(
    title: 'TabOverview Example',
    debugShowCheckedModeBanner: false,
    theme: exampleTheme,
    home: const TabOverviewExample(),
  ),
);

/// Numbered tabs in a tab switcher, as live thumbnails in a grid, each of
/// which zooms into its page:
///
/// 1. A [TabOverviewController] holds the tabs, and whether they show as a
///    grid of thumbnails or as pages.
/// 2. [TabOverview.builder] builds each tab's page, which the grid shows,
///    scaled down, as its thumbnail.
/// 3. A tap zooms a thumbnail into its page, and the buttons switch between
///    the grid and the pages, close the active tab and add one.
class TabOverviewExample extends StatefulWidget {
  const TabOverviewExample({super.key});

  @override
  State<TabOverviewExample> createState() => TabOverviewExampleState();
}

class TabOverviewExampleState extends State<TabOverviewExample> {
  // 1. The controller, with tabs 1 to 5 open in the grid.
  final controller = TabOverviewController<int>(initialTabs: [1, 2, 3, 4, 5]);

  // The number of the last tab added, so each new tab has one of its own.
  var _lastTab = 5;

  @override
  Widget build(BuildContext context) {
    final padding = MediaQuery.viewPaddingOf(context);
    return Scaffold(
      backgroundColor: Theme.of(context).colorScheme.surfaceContainerHigh,
      // 2. The tab switcher: the grid of thumbnails, or the tabs' pages.
      body: TabOverview<int>.builder(
        controller: controller,
        tabBuilder: (context, tab) => TabPage(
          tab,
          // 3. A tap zooms a thumbnail into its page, and a page back out.
          onTap: () => controller.isTabExpanded(tab)
              ? controller.collapse()
              : controller.expand(tab),
        ),
        removeTabButtonBuilder: (context, tab) =>
            CloseTabButton(onPressed: () => controller.remove(tab)),
        thumbnailsGridPadding: EdgeInsets.fromLTRB(
          S.s4,
          max(padding.top, S.s4),
          S.s4,
          max(padding.bottom, S.s4),
        ),
        thumbnailDecoration: ShapeDecoration(shape: squircle(S.s7)),
        // Pull a page down to zoom it back out.
        pullToCollapse: true,
        // Drag with the mouse too, to turn the page and to pull it down.
        scrollBehavior: const MaterialScrollBehavior().copyWith(
          dragDevices: PointerDeviceKind.values.toSet(),
        ),
      ),
      floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
      floatingActionButton: TabButtons(
        // 3. Switch between the grid and the pages.
        onSwitchView: controller.toggleMode,
        // 3. Close the active tab, if any is left.
        onClose: () {
          final tab = controller.activeTab;
          if (tab != null) controller.remove(tab);
        },
        // 3. Add a tab.
        onAdd: () => controller.add(++_lastTab),
      ),
    );
  }
}

Questions? Answers. #

How do I make a tab switcher in Flutter?

Give a TabOverviewController your tabs, and build their pages in TabOverview.builder, as the example above does. The tabs show as live thumbnails in a grid: expand zooms one into its page, and collapse, or a pull down with pullToCollapse, zooms it back out. A tab can be anything: a number, as here, or your own model of a document, a chat or a form.

Is this a TabBar?

No. Flutter's TabBar shows a row of tab labels, and its TabBarView swipes between their pages. tab_overview shows multiple tabs at once, each as a thumbnail of its page, and zooms the tapped one into a full page, where a swipe turns to the next tab. People add, close and reorder the tabs as they go.

How do I add and close tabs dynamically?

Call the controller's add with a new tab, or remove with the tab to close, as the example's buttons do. A tab's close button and a swipe to the left close it too, and isTabRemovable keeps a tab from being closed.

How do I reorder tabs with drag and drop?

There's nothing to add: a long press lifts a thumbnail, and a drag moves it, as the others slide out of its way. isTabReorderable keeps a tab in its place, and addTabsReorderedListener tells you when the order changes, which the controller's tabs then has.

What happens to a tab's state when it zooms?

The tab's page is built anew as it zooms in or out, so a State in it starts over. Keep what should carry over, such as a scroll offset or typed text, in your tab object, and give it to the page as it's built. Tabs added, closed or moved around a tab keep its state.

Can a thumbnail look different from its page?

Yes. tabThumbnailBuilder builds a tab's thumbnail, such as a card with the tab's title, in place of its scaled-down page.

1. Recorded from the example frame by frame, at 60 fps, in an iPhone 15 frame.

6
likes
160
points
864
downloads

Documentation

API reference

Publisher

verified publisherigorkurilenko.dev

Weekly Downloads

Tab switcher with live thumbnails: show the tabs your app keeps open in a grid, zoom one into a full page, swipe between pages, drag to reorder and swipe to close.

Repository (GitHub)
View/report issues

Topics

#tabs #transition #animation #drag-and-drop #reorderable

License

Apache-2.0 (license)

Dependencies

animated_reorderable, flutter, hero_here

More

Packages that depend on tab_overview