8
Creating an App's Navigation

WHAT YOU WILL LEARN IN THIS CHAPTER

  • How to use the Navigator widget to navigate between pages
  • How hero animation allows a widget transition to fly into place from one page to another
  • How to display a horizontal list of BottomNavigationBarItems containing an icon and a title at the bottom of the page
  • How to enhance the look of a bottom navigation bar with the BottomAppBar widget, which allows enabling a notch
  • How to display a horizontal row of tabs with TabBar
  • How to use TabBarView in conjunction with TabBar to display the page of the selected tab
  • How Drawer allows the user to slide a panel from left or right
  • How to use the ListView constructor to build a short list of items quickly
  • How to use the ListView constructor with the Drawer widget to show a menu list

In this chapter, you'll learn that navigation is a major component in a mobile application. Good navigation creates a great user experience (UX) by making it easy to access information. For example, imagine making a journal entry, and when trying to select a tag, it's not available, so you need to create a new one. Do you close the entry and go to Settings ➪ Tags to add a new one? That would be clunky. Instead, the user needs the ability to add a new tag on the fly and appropriately navigate to select or add a tag from their current position. When designing an app, always keep in mind how the user would navigate to different parts of the app with the least number of taps.

Animation while navigating to different pages is also important if it helps to convey an action, rather than simply being a distraction. What does this mean? Just because you can show fancy animations does not mean you should. Use animations to enhance the UX, not frustrate the user.

USING THE NAVIGATOR

The Navigator widget manages a stack of routes to move between pages. You can optionally pass data to the destination page and back to the original page. To start navigating between pages, you use the Navigator.push, pushNamed, and pop methods. (You'll learn how to use the pushNamed method in the “Using the Named Navigator Route” section of this chapter.) Navigator is incredibly smart; it shows native navigation on iOS or Android. For example, in iOS when navigating to a new page, you usually slide the next page from the right side of the screen toward the left. In Android when navigating to a new page, you typically slide the next page from the bottom of the screen toward the top. To summarize, in iOS, the new page slides in from the right, and in Android, it slides in from the bottom.

The following example shows you how to use the Navigator.push method to navigate to the About page. The push method passes the BuildContext and Route arguments. To push a new Route argument, you create an instance of the MaterialPageRoute class that replaces the screen with the appropriate platform (iOS or Android) animation transition. In the example, the fullscreenDialog property is set to true to present the About page as a full‐screen modal dialog. By setting the fullscreenDialog property to true, the About page app bar automatically includes a close button. In iOS, the modal dialog transition presents the page by sliding from the bottom of the screen toward the top, and this is also the default for Android.

Navigator.push(
 context,
 MaterialPageRoute(
  fullscreenDialog: true,
  builder: (context) => About(),
 ),
);

The following example shows how to use the Navigator.pop method to close the page and navigate back to the previous page. You call the Navigator.pop(context) method by passing the BuildContext argument, and the page closes by sliding from the top of the screen toward the bottom. The second example shows how to pass a value back to the previous page.

// Close page
Navigator.pop(context);

// Close page and pass a value back to previous page
Navigator.pop(context, 'Done');

Using the Named Navigator Route

An alternate way to use Navigator is to refer to the page that you are navigating to by the route name. The route name starts with a slash, and then comes the route name. For example, the About page route name is '/about'. The list of routes is built into the MaterialApp() widget. The routes have a Map of String and WidgetBuilder where the String is the route name, and the WidgetBuilder has a builder to build the contents of the route by the Class name (About) of the page to open.

routes: <String, WidgetBuilder>{
 '/about': (BuildContext context) => About(),
 '/gratitude': (BuildContext context) => Gratitude(),
},

To call the route, the Navigator.pushNamed() method is called by passing two arguments. The first argument is context, and the second is the route name.

Navigator.pushNamed(context, '/about');

USING HERO ANIMATION

The Hero widget is a great out‐of‐the‐box animation to convey the navigation action of a widget flying into place from one page to another. The hero animation is a shared element transition (animation) between two different pages.

To visualize the animation, imagine seeing a superhero flying into action. For example, you have a list of journal entries with a photo thumbnail, the user selects an entry, and you see the photo thumbnail transition to the detail page by moving and growing to full size. The photo thumbnail is the superhero, and when tapped, it flies into action by moving from the list page to the detail page and lands perfectly on the correct location at the top of the detail page showing the full photo. When the detail page is dismissed, the Hero widget flies back to the original page, position, and size. In other words, the animation shows the photo thumbnail moving and growing into place from the list page to the detail page, and once the detail page is dismissed, the animation and size are reversed. The Hero widget has all of these features built in; there's no need to write custom code to handle the size and animation between pages.

To continue with the previous scenario, you wrap the list page Image widget as a child of the Hero widget and assign a tag property name. Repeat the same steps for the detail page and make sure the tag property value is the same in both pages.

// List page
Hero(
 tag: 'photo1',
 child: Image(
  image: AssetImage("assets/images/coffee.png"),
 ),
),

// Detail page
Hero( tag: 'photo1',
 child: Container(
  child: Image(
   image: AssetImage("assets/images/coffee.png"),
  ),
 ),
),

The Herochild widget is marked for hero animation. When the Navigator pushes or pops a PageRoute, the entire screen's content is replaced. This means during the animation transition the Hero widget is not shown in the original position in both the old and new routes, but it moves and resizes from one page to another. Each Hero tag must be unique and match on both the originating and landing pages.

USING THE BOTTOMNAVIGATIONBAR

BottomNavigationBar is a Material Design widget that displays a list of BottomNavigationBarItems that contains an icon and a title at the bottom of the page (Figure 8.1). When the BottomNavigationBarItem is selected, the appropriate page is built.

Screenshot of final BottomNavigationBar with icons and titles.

FIGURE 8.1: Final BottomNavigationBar with icons and titles

USING THE BOTTOMAPPBAR

The BottomAppBar widget behaves similarly to the BottomNavigationBar, but it has an optional notch along the top. By adding a FloatingActionButton and enabling the notch, the notch provides a nice 3D effect so it looks like the button is recessed into the navigation bar (Figure 8.2). For example, to enable the notch, you set the BottomAppBarshape property to a NotchedShape class like the CircularNotchedRectangle() class and set the ScaffoldfloatingActionButtonLocation property to FloatingActionButtonLocation.endDocked or centerDocked. Add to the ScaffoldfloatingActionButton property a FloatingActionButton widget, and the result shows the FloatingActionButton embedded into the BottomAppBar widget, which is the notch.

Screenshot of BottomAppBar with embedded FloatingActionButton creating a notch.

FIGURE 8.2: BottomAppBar with embedded FloatingActionButton creating a notch

BottomAppBar(
 shape: CircularNotchedRectangle(),
)

floatingActionButtonLocation: FloatingActionButtonLocation.endDocked,
floatingActionButton: FloatingActionButton(
 child: Icon(Icons.add),
),

USING THE TABBAR AND TABBARVIEW

The TabBar widget is a Material Design widget that displays a horizontal row of tabs. The tabs property takes a List of Widgets, and you add tabs by using the Tab widget. Instead of using the Tab widget, you could create a custom widget, which shows the power of Flutter. The selected Tab is marked with a bottom selection line.

The TabBarView widget is used in conjunction with the TabBar widget to display the page of the selected tab. Users can swipe left or right to change content or tap each Tab.

Both the TabBar (Figure 8.3) and TabBarView widgets take a controller property of TabController. The TabController is responsible for syncing tab selections between a TabBar and a TabBarView. Since the TabController syncs the tab selections, you need to declare the SingleTickerProviderStateMixin to the class. In Chapter 7, “Adding Animation to an App,” you learned how to implement the Ticker class that is driven by the ScheduleBinding.scheduleFrameCallback reporting once per animation frame. It is trying to sync the animation to be as smooth as possible.

“Screenshot of TabBar in the Scaffold bottomNavigationBar property.”

FIGURE 8.3: TabBar in the Scaffold bottomNavigationBar property

USING THE DRAWER AND LISTVIEW

You might be wondering why I'm covering the ListView in this navigation chapter. Well, it works great with the Drawer widget. ListView widgets are used quite often for selecting an item from a list to navigate to a detailed page.

Drawer is a Material Design panel that slides horizontally from the left or right edge of the Scaffold, the device screen. Drawer is used with the Scaffolddrawer (left‐side) property or endDrawer (right‐side) property. Drawer can be customized for each individual need but usually has a header to show an image or fixed information and a ListView to show a list of navigable pages. Usually, a Drawer is used when the navigation list has many items.

To set the Drawer header, you have two built‐in options, the UserAccountsDrawerHeader or the DrawerHeader. The UserAccountsDrawerHeader is intended to display the app's user details by setting the currentAccountPicture, accountName, accountEmail, otherAccountsPictures, and decoration properties.

// User details
UserAccountsDrawerHeader(
 currentAccountPicture: Icon(Icons.face,),
 accountName: Text('Sandy Smith'),
 accountEmail: Text('[email protected]'),
 otherAccountsPictures: <Widget>[
  Icon(Icons.bookmark_border),
 ],
 decoration: BoxDecoration(
  image: DecorationImage(
   image: AssetImage('assets/images/home_top_mountain.jpg'),
   fit: BoxFit.cover,
  ),
 ),
),

DrawerHeader is intended to display generic or custom information by setting the padding, child, decoration, and other properties.

// Generic or custom information
DrawerHeader(
 padding: EdgeInsets.zero,
 child: Icon(Icons.face),
 decoration: BoxDecoration(color: Colors.blue),
),

The standard ListView constructor allows you to build a short list of items quickly. The next chapter will go into more depth on how to use the ListView. See Figure 8.4.

Screenshot of Drawer and ListView.

FIGURE 8.4: Drawer and ListView

SUMMARY

In this chapter, you learned to use the Navigator widget to manage a stack of routes so as to allow navigation between pages. You optionally passed data to the navigation page and back to the original page. The hero animation allows a widget transition to fly into place from one page to another. The widget to animate from and to is wrapped in a Hero widget by a unique key.

You used the BottomNavigationBar widget to display a horizontal list of BottomNavigationBarItems containing an icon and a title at the bottom of the page. When the user taps each BottomNavigationBarItem, the appropriate page is displayed. To enhance the look of a bottom navigation bar, you used the BottomAppBar widget and enabled the optional notch. The notch is the result of embedding a FloatingActionButton to a BottomAppBar by setting the BottomAppBarshape to a CircularNotchedRectangle() class and setting the ScaffoldfloatingActionButtonLocation property to FloatingActionButtonLocation.endDocked.

The TabBar widget displays a horizontal row of tabs. The tabs property takes a List of widgets, and tabs are added by using the Tab widget. The TabBarView widget is used in conjunction with the TabBar widget to display the page of the selected tab. Users can swipe left or right to change content or tap each Tab. The TabController class handled the syncing of the TabBar and selected TabBarView. The TabController requires the use of withSingleTickerProviderStateMixin in the class.

The Drawer widget allows the user to slide a panel from left or right. The Drawer widget is added by setting the Scaffolddrawer or endDrawer property. To easily align menu items in a list, you pass a ListView as a child of the Drawer. Since this menu list is short, you use the standard ListView constructor instead of a ListView builder, which is covered in the next chapter. You have two prebuilt drawer header options, UserAccountsDrawerHeader or DrawerHeader. When the user taps one of the menu items, the onTap property calls Navigator.pop() to close Drawer and calls Navigator.push() to navigate to the selected page.

In the next chapter, you'll learn to use different types of lists. You will take a look at the ListView, GridView, Stack, Card, and my favorite—CustomScrollView to use Slivers.

image WHAT YOU LEARNED IN THIS CHAPTER

TOPIC KEY CONCEPTS
Navigator The Navigator widget manages a stack of routes to move between pages.
Hero animation The Hero widget is used to convey a navigation animation and size for a widget to fly into place from one page to another. When the second page is dismissed, the animation is reversed to the originating page.
BottomNavigationBar BottomNavigationBar displays a horizontal list of BottomNavigationBarItem items containing an icon and a title at the bottom of the page.
BottomAppBar The BottomAppBar widget behaves like the BottomNavigationBar, but it has an optional notch along the top.
TabBar The TabBar widget displays a horizontal row of tabs. The tabs property takes a list of widgets, and tabs are added by using the Tab widget.
TabBarView The TabBarView widget is used in conjunction with the TabBar widget to display the page of the selected tab.
Drawer The Drawer widget allows the user to slide a panel from left or right.
ListView The standard ListView constructor allows you to build a short list of items quickly.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset