Xamarin Forms TabbedPage

The TabbedPage is, as you’d probably expect, a page that hosts ContentPage and NavigationPage elements and displays “tabs” for selecting between those pages.

You cannot have a ContentPage hosting a tab control within it without using a third party control or writing your own.

Let’s create a TabbedPage based application

Let’s take look at implementing a TabbedPage based UI in Visual Studio 2017 (the Visual Studio for Mac project template creates a tabbed page application by default).

  • In Visual Studio 2017, File | New | Project
  • In the search box, type mobile (or select Cross-Platform | Mobile App (Xamarin.Forms))
  • Give your project a name, mine’s TabbedPageExample
  • Select Blank App, I’m aiming to write for all three listed platforms and so keep all three checked, I then select .NET Standard (or Shared Project if you prefer)
  • Build the project just to get NuGet packages updated etc.

We’ve got our project created and by default on Visual Studio 2017 you’ll have created a MainPage.xaml which is a ContentPage, we’re going to change this to a TabbedPage

  • Open the MainPage.xaml and change ContentPage to TabbedPage
  • Before we leave MainPage.xaml remove the StackLayout and everything within it, we won’t be needing this
  • Open the MainPage.xaml.cs and change ContentPage to TabbedPage here also
  • Right mouse click on the shared project (the one not suffixed with a platform name) and select Add | New Item. Select The Xamarin.Forms item on the left, then Content Page (note: not the Content Page (C#) as we’re going to just writing XAML here). Do this two more times as these will form our three tab pages. Mine are named ProjectsPage, HistoryPage and AboutPage.
  • Back in MainPage.xaml, add the following, within the TabbedPage element (i.e. where StackLayout used to reside)
    <local:ProjectsPage />
    <local:HistoryPage />
    <local:AboutPage />
    

    Note: For those not used to XAML etc. the local text is an xmlns (namespace), automatically added to our XAML files.

  • Now in each XAML file (ProjectsPage.xaml, History.xaml etc.) just change the Label to use the display then name as the page (just so we can see the page changes when we click on a tab). Also add a Title=”” to each ContentPage as an attribute and inside the “” put the tab name, i.e. Projects, History, About

If you build and run this now (I’m using the Visual Studio Emulator for Android to view things on Windows), you should see – on Android and UWP three tabs with the labels all at the top of the screen, if you run this against an iOS emulator/simulator the tabs will be at the bottom of the screen and the text is very small – this is because Android and UWP, by default, show just text, iOS be default shows text and an image, so the small text is that size to accommodate the image.

Platform specific XAML

We’re trying to keep all our shared code, whether these are services, other libraries or UI, in the shared project. Xamarin.Forms allows us to conditionally add XAML based upon the platform, i.e.

<ContentPage.Icon>
   <OnPlatform x:TypeArguments="FileImageSource">
      <On Platform="iOS" Value="history.png"/>
   </OnPlatform>
</ContentPage.Icon>

For each ContentPage we add the above as a child to the ContentPage element. the x:TypeArguments refers to the type of objects for the On Platform Value, i.e. these are Image file locations in this case.

As this adds platforms specific conditions to the XAML, we would then create the various .png images, not within the shared code but instead within the TabbedPageExample.iOS project, into the Resources folder and marked as BundleResource.

Each image file should come in three sizes, so let’s suppose we create an file about.png (for the About tab). This should be 30 x 30 pixels in size. Then the next file should be about@2x.png and should be 60 x 60 pixels, finally the last file should be about@3x.png and should be 90 x 90 pixels in size.

Once you’ve created a group of three image’s per tab (as outlined) and ensured their Build Action is BundleResource and got the XAML correctly references each of the smaller images, then you should find that when you run the app. on iOS, text and an image is displayed on each tab. Whilst Android and UWP is solely text. By only including the images in the iOS project you’re not wasting space on the other projects that do not use them.

Code

Code is available on github.