left-icon

Xamarin.Forms for macOS Succinctly®
by Alessandro Del Sole

Previous
Chapter

of
A
A
A

CHAPTER 6

Pages and Navigation

Pages and Navigation


In the previous chapters, we went over the basics of layouts and views, which are the fundamental building blocks of the user interface in mobile applications. However, I demonstrated how to use layouts and views within a single page, while real-world mobile apps are made of multiple pages. Android and iOS provide a number of different pages that allow you to display content in several ways, and to provide the best user experience possible based on the content you need to present.

Xamarin.Forms provides unified page models you can use from your single, shared C# codebase that work cross-platform. It also provides an easy-to-use navigation framework, the infrastructure you use to move between pages. Pages and navigation are the topics of this chapter, and the last pieces of the user interface framework you need to know to build beautiful, native apps with Xamarin.Forms.

Note: In order to follow the examples in this chapter, create a new Xamarin.Forms solution based on the PCL code-sharing strategy. The name is up to you. Every time a new page is discussed, just clean the content of the MainPage.xaml and MainPage.xaml.cs files (except for the constructor) and write the new code.

Introducing and creating pages

Xamarin.Forms provides many page objects that you can use to set up the user interfaces of your applications. Pages are root elements in the visual hierarchy, and each page allows you to add only one visual element, typically a root layout with other layouts and visual elements nested inside the root. From a technical point of view, all the page objects in Xamarin.Forms derive from the abstract Page class, which provides the basic infrastructure of each page, including common properties such as Content, which is definitely the most important property that you assign with the root visual element. Table 7 describes the available pages in Xamarin.Forms.

Table 7: Pages in Xamarin.Forms

Page Type

Description

ContentPage

Displays a single view object

TabbedPage

Facilitates navigating among child pages using tabs

CarouselPage

Facilitates using the swipe gesture among child pages

MasterDetailPage

Manages two separate panes, which includes a flyout control

NavigationPage

Provides the infrastructure for navigating among pages

The next sections describe available pages in more detail. Remember that Visual Studio provides item templates for different page types, so you can right-click the PCL project in the Solution pad, select Add > New File, and in the New File dialog, you will see templates for each page described in Table 7.

Single views with the ContentPage

The ContentPage object is the simplest page possible and allows for displaying a single visual element. You already looked at some examples of the ContentPage previously, but it is worth mentioning its Title property. This property is particularly useful when the ContentPage is used in pages with built-in navigation, such as TabbedPage and CarouselPage, because it helps identify the active page. The core of the ContentPage is the Content property, which you assign with the visual element you want to display. The visual element can be either a single control or a layout; the latter allows you to create complex visual hierarchies and real-world user interfaces. In XAML, the tag for the Content property can be omitted, which is also common practice (also notice Title):

<?xml version="1.0" encoding="utf-8" ?>

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"

             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"

             xmlns:local="clr-namespace:App1"

             Title="Main page"

             x:Class="App1.MainPage">

 

    <Label Text="A content page"/>

 

</ContentPage>

The ContentPage can be used individually or as the content of other pages discussed in the next sections.

Splitting contents with the MasterDetailPage

The MasterDetailPage is a very important page, since it allows you to split contents into two separate categories: generic and detailed. The user interface provided by the MasterDetailPage is very common in Android and iOS apps. It offers a flyout on the left (the master part) that you can swipe to show and hide it, and a second area on the right that displays more detailed content (the detail part). For example, a very common scenario for this kind of page is displaying a list of topics or settings in the master and the content for the selected topic or setting in the detail. Both the master and the detail parts are represented by ContentPage objects. A typical declaration for a MasterDetailPage looks like Code Listing 11.

Code Listing 11

<?xml version="1.0" encoding="utf-8" ?>

<MasterDetailPage xmlns="http://xamarin.com/schemas/2014/forms"

             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"

             xmlns:local="clr-namespace:App1"

             Title="Main page"

             x:Class="App1.MainPage">

 

    <MasterDetailPage.Master>

        <ContentPage>

            <Label Text="This is the Master" HorizontalOptions="Center"

                   VerticalOptions="Center"/>

        </ContentPage>

    </MasterDetailPage.Master>

    <MasterDetailPage.Detail>

        <ContentPage>

            <Label Text="This is the Details" HorizontalOptions="Center"

                   VerticalOptions="Center"/>

        </ContentPage>

    </MasterDetailPage.Detail>

</MasterDetailPage>

As you can see, you populate the Master and Detail properties with the appropriate ContentPage objects. In real-world apps, you might have a list of topics in the Master, and then you might show details for a topic in the Detail when the user taps one in the Master’s content.

Note: Every time you change the root page from ContentPage to another kind of page, such as MasterDetailPage, you also need to change the inheritance in the code-behind. For example, if you open the C# MainPage.xaml.cs file, you will see that MainPage inherits from ContentPage, but in XAML, you replaced this object with MasterDetailPage. So, you also need to make MainPage inherit from MasterDetailPage. If you forget this, the compiler will report an error. This note is valid for the pages discussed in the next sections as well.

Figures 33 and 34 show the master and detail parts, respectively. You can simply swipe from the left to enable the master flyout, and then swipe back to hide it. You can also control the flyout programmatically by assigning the IsPresented property with true (visible) or false (hidden). This is useful when the app is in landscape mode, because the flyout is automatically opened by default.

Figure 33: MasterDetailPage: The flyout

of the master

Figure 34: MasterDetailPage: The detail

Displaying content within tabs with the TabbedPage

Sometimes you might need to categorize multiple pages by topic, or by activity type. When you have a small amount of content, you can take advantage of the TabbedPage, which can group multiple ContentPage objects into tabs for easy navigation. The TabbedPage can be declared as shown in Code Listing 12.

Code Listing 12

<?xml version="1.0" encoding="utf-8" ?>

<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"

             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"

             xmlns:local="clr-namespace:App1"

             Title="Main page"

             x:Class="App1.MainPage">

 

    <TabbedPage.Children>

        <ContentPage Title="First">

            <Label Text="This is the first page" HorizontalOptions="Center"

                   VerticalOptions="Center"/>

        </ContentPage>

        <ContentPage Title="Second">

            <Label Text="This is the second page" HorizontalOptions="Center"

                   VerticalOptions="Center"/>

        </ContentPage>

        <ContentPage Title="Third">

            <Label Text="This is the third page" HorizontalOptions="Center"

                   VerticalOptions="Center"/>

        </ContentPage>

    </TabbedPage.Children>

</TabbedPage>

As you can see, you populate the Children collection with multiple ContentPage objects. Providing a Title to each ContentPage is of primary importance, since the title’s text is displayed in each tab, as demonstrated in Figure 35.

Displaying grouped contents with the TabbedPage

Figure 35: Displaying grouped contents with the TabbedPage

Of course, the TabbedPage works well with a small number of child pages, typically between three and four pages.

Swiping pages with the CarouselPage

The CarouselPage is similar to the TabbedPage, but instead of having tabs, you can use the swipe gesture to switch among child pages. For example, the CarouselPage could be perfect for displaying a gallery of pictures. Code Listing 13 shows how to declare a CarouselPage.

Code Listing 13

<?xml version="1.0" encoding="utf-8" ?>

<CarouselPage xmlns="http://xamarin.com/schemas/2014/forms"

             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"

             xmlns:local="clr-namespace:App1"

             Title="Main page"

             x:Class="App1.MainPage">

 

    <CarouselPage.Children>

        <ContentPage Title="First">

            <Label Text="This is the first page" HorizontalOptions="Center"

                   VerticalOptions="Center"/>

        </ContentPage>

        <ContentPage Title="Second">

            <Label Text="This is the second page" HorizontalOptions="Center"

                   VerticalOptions="Center"/>

        </ContentPage>

        <ContentPage Title="Third">

            <Label Text="This is the third page" HorizontalOptions="Center"

                   VerticalOptions="Center"/>

        </ContentPage>

    </CarouselPage.Children>

</CarouselPage>

Figure 36 shows how the CarouselPage appears.

Swiping contents with the CarouselPage

Figure 36: Swiping contents with the CarouselPage

Navigating among pages

Note: In the spirit of the Succinctly series, this section explains the most important concepts and topics of page navigation. However, there are tips and considerations that are specific to each platform that you have to know when dealing with navigation in Xamarin.Forms. With regard to this, check out the official documentation.

Most mobile apps offer their content through multiple pages. In Xamarin.Forms, navigating among pages is very simple because of a built-in navigation framework. First of all, in Xamarin.Forms you leverage navigation features through the NavigationPage object. This kind of page must be instantiated, passing an instance of the first page in the stack of navigation to its constructor. This is typically done in the App.xaml.cs file, where you replace the assignment of the MainPage property with the following code:

public App()

{

    InitializeComponent();

 

    MainPage = new NavigationPage(new MainPage());

}

Wrapping a root page into a NavigationPage will not only enable the navigation stack, but will also enable the navigation bar on both Android and iOS, whose text will be the value of the Title property of the current page object, represented by the CurrentPage read-only property. Now suppose you added another page of type ContentPage to the PCL project, called SecondaryPage.xaml. The content of this page is not important at this point; just set its Title property with some text. If you want to navigate from the first page to the second page, you use the PushAsync method as follows:

await Navigation.PushAsync(new SecondaryPage());

The Navigation property, exposed by each Page object, represents the navigation stack at the application level and provides methods for navigating between pages in a LIFO (last-in, first-out) approach. PushAsync navigates to the specified page instance; PopAsync, invoked from the current page, removes the current page from the stack and goes back to the previous page. Similarly, PushModalAsync and PopModalAsync allow you to navigate between pages modally. The following lines of code demonstrate this:

// removes SecondaryPage from the stack and goes back to the previous page

await Navigation.PopAsync();

// displays the specified page as a modal page

await Navigation.PushModalAsync(new SecondaryPage());

await Navigation.PopModalAsync();

Figure 37 shows how the navigation bar appears on Android and iOS when navigating to another page.

The navigation bar offered by the NavigationPage object

Figure 37: The navigation bar offered by the NavigationPage object

Users can simply touch the Back button on the navigation bar to go back to the previous page. However, when you implement modal navigation, you cannot take advantage of the built-in navigation mechanism offered by the navigation bar, so it is your responsibility to implement code that allows going back to the previous page. Modal navigation can be useful if you must be able to intercept a tap on the back button on each platform. In fact, Android devices have a built-in hardware Back button that you can manage with events, but iOS does not. In iOS, you only have the Back button provided by the navigation bar, but this cannot be handled with any events. So, in this case, modal navigation can be a good option to intercept user actions.

Passing objects between pages

The need to exchange data between pages is not uncommon. You can change or overload a Page’s constructor and pass a parameter of the desired type. Then, when you call PushAsync and pass the instance of the new page, you will be able to supply the argument that is necessary to the new page’s constructor.

Animating transitions between pages

By default, the navigation includes an animation that makes the transition from one page to another nicer. However, you can disable animations by simply passing false as the argument of PushAsync and PushModalAsync.

Managing the page lifecycle

Every Page object exposes the OnAppearing and OnDisappearing events, raised right before the page is rendered, and right before the page is removed from the stack, respectively. Their code looks like the following:

protected override void OnAppearing()

{

    // Replace with your code…

    base.OnAppearing();

}

 

protected override void OnDisappearing()

{

    // Replace with your code…

    base.OnDisappearing();

}

Actually, these events are not strictly related to navigation, since they are available to any page, including individual pages. However, it is with navigation that they become very important, especially when you need to execute some code at specific moments in the page lifecycle. For a better understanding of the flow, think of the page constructor: this is invoked the very first time a page is created. Then, OnAppearing is raised right before the page is rendered on screen. When the app navigates to another page, OnDisappearing is invoked, but this does not destroy the current page instance (and this makes perfect sense). When the app navigates back from the second page to the first page, this is not created again because it is still in the navigation stack, so its constructor will not be invoked, while OnAppearing will. So, within the OnAppearing method body, you can write code that will be executed every time the page is shown, while in the constructor, you can write code that will be executed only once.

Handling the hardware Back button

Android devices have a built-in hardware Back button that users can use instead of the Back button in the navigation bar. You can detect if the user presses the hardware Back button by handling the OnBackButtonPressed event as follows:

protected override bool OnBackButtonPressed()

{

    return base.OnBackButtonPressed(); // replace with your logic here…

}

Simply put your logic in the method body. The default behavior is to suspend the app, so you might want to override this with PopAsync to return to the previous page. This event does not intercept pressing the Back button in the navigation bar, which implies it has no effect on iOS devices.

Chapter summary

This chapter introduced the available pages in Xamarin.Forms, explaining how you can display single-view content with the ContentPage object, group content into tabs with the TabbedPage, swipe content with the CarouselPage, and group contents into two categories with the MasterDetail page object. In the second part of the chapter, you looked at how the NavigationPage object provides a built-in navigation framework that not only displays a navigation bar, but also allows for navigating between pages programmatically. Finally, you looked at how the page lifecycle works, including the difference between page creation and page rendering.

In the next chapter, you will look at information about two important and powerful features in Xamarin.Forms: resources and data binding.

Scroll To Top
Disclaimer
DISCLAIMER: Web reader is currently in beta. Please report any issues through our support system. PDF and Kindle format files are also available for download.

Previous

Next



You are one step away from downloading ebooks from the Succinctly® series premier collection!
A confirmation has been sent to your email address. Please check and confirm your email subscription to complete the download.