Using the CupertinoTabScaffold Widget for Implementing iOS-Style Tab Navigation in Flutter

Flutter allows developers to build beautiful, natively compiled applications for mobile, web, and desktop from a single codebase. One of Flutter’s strengths is its ability to adapt the look and feel of the UI to match the platform it’s running on. For iOS, the CupertinoTabScaffold widget is essential for creating tabbed navigation that adheres to Apple’s design guidelines. This blog post explores how to use the CupertinoTabScaffold widget to implement iOS-style tab navigation in Flutter apps.

What is CupertinoTabScaffold?

The CupertinoTabScaffold widget is part of the flutter/cupertino library and is designed to create a tabbed interface that looks and feels like native iOS applications. It provides a structure that includes a CupertinoNavigationBar at the top and a CupertinoTabBar at the bottom, with content areas for each tab.

Why Use CupertinoTabScaffold?

  • iOS Aesthetics: Provides an authentic iOS look and feel.
  • Navigation Consistency: Adheres to iOS navigation patterns, offering a familiar experience for users.
  • Integration: Seamlessly integrates with other Cupertino widgets for a cohesive UI.

How to Implement CupertinoTabScaffold

Implementing CupertinoTabScaffold involves setting up the basic structure with tabs and content. Here’s a step-by-step guide:

Step 1: Import Cupertino Library

Ensure you have imported the necessary Cupertino library in your Dart file:

import 'package:flutter/cupertino.dart';

Step 2: Create a CupertinoTabScaffold Widget

Wrap your root widget with CupertinoTabScaffold and define the tabBar and tabBuilder properties:


import 'package:flutter/cupertino.dart';
import 'package:flutter/widgets.dart';

class CupertinoTabScaffoldExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return CupertinoTabScaffold(
      tabBar: CupertinoTabBar(
        items: const <CupertinoTabItem>[
          CupertinoTabItem(
            icon: Icon(CupertinoIcons.home),
            label: 'Home',
          ),
          CupertinoTabItem(
            icon: Icon(CupertinoIcons.search),
            label: 'Search',
          ),
          CupertinoTabItem(
            icon: Icon(CupertinoIcons.settings),
            label: 'Settings',
          ),
        ],
      ),
      tabBuilder: (BuildContext context, int index) {
        return CupertinoTabView(
          builder: (BuildContext context) {
            return CupertinoPageScaffold(
              navigationBar: CupertinoNavigationBar(
                middle: Text('Page 1 of tab $index'),
              ),
              child: Center(
                child: CupertinoButton(
                  child: const Text('Next page'),
                  onPressed: () {
                    Navigator.of(context).push(
                      CupertinoPageRoute<void>(
                        builder: (BuildContext context) {
                          return CupertinoPageScaffold(
                            navigationBar: CupertinoNavigationBar(
                              middle: Text('Page 2 of tab $index'),
                            ),
                            child: Center(
                              child: CupertinoButton(
                                child: const Text('Back'),
                                onPressed: () {
                                  Navigator.of(context).pop();
                                },
                              ),
                            ),
                          );
                        },
                      ),
                    );
                  },
                ),
              ),
            );
          },
        );
      },
    );
  }
}

Step 3: Define Tab Items

The CupertinoTabBar requires a list of CupertinoTabItem widgets. Each item represents a tab in the tab bar.


CupertinoTabBar(
  items: const <CupertinoTabItem>[
    CupertinoTabItem(
      icon: Icon(CupertinoIcons.home),
      label: 'Home',
    ),
    CupertinoTabItem(
      icon: Icon(CupertinoIcons.search),
      label: 'Search',
    ),
    CupertinoTabItem(
      icon: Icon(CupertinoIcons.settings),
      label: 'Settings',
    ),
  ],
)

Step 4: Build Tab Content

Use the tabBuilder function to return the content for each tab. The index parameter determines which tab’s content to display.


tabBuilder: (BuildContext context, int index) {
  return CupertinoTabView(
    builder: (BuildContext context) {
      return CupertinoPageScaffold(
        navigationBar: CupertinoNavigationBar(
          middle: Text('Page 1 of tab $index'),
        ),
        child: Center(
          child: CupertinoButton(
            child: const Text('Next page'),
            onPressed: () {
              Navigator.of(context).push(
                CupertinoPageRoute<void>(
                  builder: (BuildContext context) {
                    return CupertinoPageScaffold(
                      navigationBar: CupertinoNavigationBar(
                        middle: Text('Page 2 of tab $index'),
                      ),
                      child: Center(
                        child: CupertinoButton(
                          child: const Text('Back'),
                          onPressed: () {
                            Navigator.of(context).pop();
                          },
                        ),
                      ),
                    );
                  },
                ),
              );
            },
          ),
        ),
      );
    },
  );
},

Each tab content is wrapped in a CupertinoTabView, ensuring it maintains its own navigation stack.

Complete Example

Here’s a complete example putting it all together:


import 'package:flutter/cupertino.dart';
import 'package:flutter/widgets.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return CupertinoApp(
      home: CupertinoTabScaffoldExample(),
    );
  }
}

class CupertinoTabScaffoldExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return CupertinoTabScaffold(
      tabBar: CupertinoTabBar(
        items: const <CupertinoTabItem>[
          CupertinoTabItem(
            icon: Icon(CupertinoIcons.home),
            label: 'Home',
          ),
          CupertinoTabItem(
            icon: Icon(CupertinoIcons.search),
            label: 'Search',
          ),
          CupertinoTabItem(
            icon: Icon(CupertinoIcons.settings),
            label: 'Settings',
          ),
        ],
      ),
      tabBuilder: (BuildContext context, int index) {
        return CupertinoTabView(
          builder: (BuildContext context) {
            return CupertinoPageScaffold(
              navigationBar: CupertinoNavigationBar(
                middle: Text('Page 1 of tab $index'),
              ),
              child: Center(
                child: CupertinoButton(
                  child: const Text('Next page'),
                  onPressed: () {
                    Navigator.of(context).push(
                      CupertinoPageRoute<void>(
                        builder: (BuildContext context) {
                          return CupertinoPageScaffold(
                            navigationBar: CupertinoNavigationBar(
                              middle: Text('Page 2 of tab $index'),
                            ),
                            child: Center(
                              child: CupertinoButton(
                                child: const Text('Back'),
                                onPressed: () {
                                  Navigator.of(context).pop();
                                },
                              ),
                            ),
                          );
                        },
                      ),
                    );
                  },
                ),
              ),
            );
          },
        );
      },
    );
  }
}

Customization

The CupertinoTabScaffold widget offers several customization options:

  • backgroundColor: Sets the background color of the scaffold.
  • CupertinoTabBar properties: Customize the appearance of the tab bar, such as colors, border, and more.

Conclusion

The CupertinoTabScaffold widget is a powerful tool for creating iOS-style tab navigation in Flutter. By following this guide, you can easily implement a native-looking tabbed interface that enhances the user experience on iOS devices. Its seamless integration with other Cupertino widgets ensures a cohesive and polished look for your Flutter applications.