PROWAREtech
Xamarin: Tutorial - Page 11
TabbedPage
Creating tabbed pages in Xamarin could not be simplier. Use the TabbedPage
element to create a tabbed page.
Here is a single file with two tabs/pages.
<?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:HelloXamarinForms"
x:Class="HelloXamarinForms.HelloTabbedPage">
<TabbedPage.Children>
<ContentPage Title="Page1" BackgroundColor="Navy">
<Label Text="This is Page1!" TextColor="White" HorizontalOptions="Center" />
</ContentPage>
<ContentPage Title="Page2" BackgroundColor="Gray">
<Label Text="This is Page2!" TextColor="White" HorizontalOptions="Center" />
</ContentPage>
</TabbedPage.Children>
</TabbedPage>
This is the tabbed page's code behind file. Notice that the class inherits from TabbedPage
.
// HelloTabbedPage.xaml.cs
using Xamarin.Forms;
namespace HelloXamarinForms
{
public partial class HelloTabbedPage : TabbedPage
{
public HelloTabbedPage()
{
InitializeComponent();
}
}
}
A Better Way: Seperate the Pages
Each ContentPage
can have its own XAML file. This is the preferred method. This is the main page
(App.MainPage
) for the application. It is the tabbed page (TabbedPage
). Page1
and Page2
are both ContentPage
.
<?xml version="1.0" encoding="utf-8"?>
<!--HelloTabbedPage.xaml-->
<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:HelloXamarinForms"
x:Class="HelloXamarinForms.HelloTabbedPage">
<local:Page1 />
<local:Page2 />
</TabbedPage>
This file goes unchanged.
// HelloTabbedPage.xaml.cs
using Xamarin.Forms;
namespace HelloXamarinForms
{
public partial class HelloTabbedPage : TabbedPage
{
public HelloTabbedPage()
{
InitializeComponent();
}
}
}
This is the first page's (Page1
) files:
<?xml version="1.0" encoding="UTF-8"?>
<!--Page1.xaml-->
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="HelloXamarinForms.Page1"
Title="Page 1"
BackgroundColor="Blue">
<ContentPage.Padding>
<OnPlatform x:TypeArguments="Thickness" iOS="0, 20, 0, 0" />
</ContentPage.Padding>
<ContentPage.Content>
<Label TextColor="White" Text="This is page 1" HorizontalOptions="Center" />
</ContentPage.Content>
</ContentPage>
// Page1.xaml.cs
using System;
using System.Collections.Generic;
using Xamarin.Forms;
namespace HelloXamarinForms
{
public partial class Page1 : ContentPage
{
public Page1()
{
InitializeComponent();
}
}
}
This is the second page's (Page2
) files:
<?xml version="1.0" encoding="UTF-8"?>
<!--Page2.xaml-->
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="HelloXamarinForms.Page2"
Title="Page 2"
BackgroundColor="Navy">
<ContentPage.Padding>
<OnPlatform x:TypeArguments="Thickness" iOS="0, 20, 0, 0" />
</ContentPage.Padding>
<ContentPage.Content>
<Label TextColor="White" Text="THis is Page 2" HorizontalOptions="Center" />
</ContentPage.Content>
</ContentPage>
// Page2.xaml.cs
using System;
using System.Collections.Generic;
using Xamarin.Forms;
namespace HelloXamarinForms
{
public partial class Page2 : ContentPage
{
public Page2()
{
InitializeComponent();
}
}
}
And the App files:
<?xml version="1.0" encoding="utf-8"?>
<!--App.xaml-->
<Application xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="HelloXamarinForms.App">
<Application.Resources>
<!-- Application resource dictionary -->
</Application.Resources>
</Application>
Notice here that MainPage
is assigned the new tabbed page object.
// App.xaml.cs
using Xamarin.Forms;
namespace HelloXamarinForms
{
public partial class App : Application
{
public App()
{
InitializeComponent();
MainPage = new HelloTabbedPage();
}
protected override void OnStart()
{
// Handle when your app starts
}
protected override void OnSleep()
{
// Handle when your app sleeps
}
protected override void OnResume()
{
// Handle when your app resumes
}
}
}
MasterDetailPage
MasterDetailPage
manages two pages, a master page and a detail page. Its behavior is unique overall and unique
across device types. On iOS, the two pages are side-by-side and slide. On Android, the master overlays the detail.
The IsPresented
property set to true means that the master page is open initially.
Example Code
<?xml version="1.0" encoding="utf-8"?>
<!--MasterDetailPage.xaml-->
<MasterDetailPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:HelloXamarinForms"
x:Class="HelloXamarinForms.MasterDetailPageXaml"
IsPresented="True">
<MasterDetailPage.Master>
<local:MasterPage />
</MasterDetailPage.Master>
<MasterDetailPage.Detail>
<NavigationPage>
<x:Arguments>
<local:DetailPage />
</x:Arguments>
</NavigationPage>
</MasterDetailPage.Detail>
</MasterDetailPage>
// MasterDetailPage.xaml.cs
namespace HelloXamarinForms
{
public partial class MasterDetailPageXaml : Xamarin.Forms.MasterDetailPage
{
public MasterDetailPageXaml()
{
InitializeComponent();
}
}
}
// App.xaml.cs
using Xamarin.Forms;
namespace HelloXamarinForms
{
public partial class App : Application
{
public App()
{
InitializeComponent();
MainPage = new MasterDetailPageXaml();
}
protected override void OnStart()
{
// Handle when your app starts
}
protected override void OnSleep()
{
// Handle when your app sleeps
}
protected override void OnResume()
{
// Handle when your app resumes
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<!--MasterPage.xaml-->
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:HelloXamarinForms"
x:Class="HelloXamarinForms.MasterPage"
BackgroundColor="Navy"
Title="Master Page"
Padding="10">
<ContentPage.Padding>
<OnPlatform x:TypeArguments="Thickness" iOS="0, 20, 0, 0" />
</ContentPage.Padding>
<Label VerticalOptions="CenterAndExpand" TextColor="White" Text=
"MASTERPAGE: Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Donec egestas imperdiet purus, sit amet aliquet sapien
gravida quis. Curabitur sed velit eu est finibus malesuada
et eu nisl. Curabitur vel sapien et massa suscipit rhoncus.
Pellentesque habitant morbi tristique senectus et netus et
malesuada fames ac turpis egestas." />
</ContentPage>
Content.Padding
for iOS is not needed on the detail page.
<?xml version="1.0" encoding="utf-8"?>
<!--DetailPage.xaml-->
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:HelloXamarinForms"
x:Class="HelloXamarinForms.DetailPage"
BackgroundColor="#333333"
Padding="10">
<Label VerticalOptions="CenterAndExpand" TextColor="White" Text=
"DETAILPAGE: Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Donec egestas imperdiet purus, sit amet aliquet sapien
gravida quis. Curabitur sed velit eu est finibus malesuada
et eu nisl. Curabitur vel sapien et massa suscipit rhoncus.
Pellentesque habitant morbi tristique senectus et netus et
malesuada fames ac turpis egestas." />
</ContentPage>
The code-behind files for MasterPage.xaml and DetailPage.xaml are unmodified.
Colors Example
This example uses data binding.
// Colors.cs
using System;
using System.Collections.Generic;
using Xamarin.Forms;
namespace HelloXamarinForms
{
public class clsColor
{
Color color;
string name, hex, rgb;
byte r, g, b;
public clsColor(Color Color, string Name)
{
this.Color = Color;
this.Name = Name;
r = (byte)(Color.R * 255);
g = (byte)(Color.G * 255);
b = (byte)(Color.B * 255);
}
// override ToString() so that it returns the data
// of the object instead of the class name
public override string ToString()
{
return Name + " " + Hex + " " + Rgb + " " + Color.ToString();
}
public Color Color
{
get
{
return color;
}
private set
{
color = value;
}
}
public string Name
{
get
{
if (name == null)
{
name = Hex;
}
return name;
}
private set
{
name = value;
}
}
// display color info in hexadecimal format
public string Hex
{
get
{
if (string.IsNullOrEmpty(hex))
{
hex = r.ToString("X2") +
g.ToString("X2") +
b.ToString("X2");
}
return hex;
}
}
// display color info in RGB format
public string Rgb
{
get
{
if (string.IsNullOrEmpty(rgb))
{
rgb = r.ToString() +
", " + g.ToString() +
", " + b.ToString();
}
return rgb;
}
}
}
public class clsColors
{
static Random rand = new Random();
static public List<clsColor> GetColors
{
get
{
List<clsColor> colors = new List<clsColor>()
{
new clsColor(Color.Accent, nameof(Color.Accent)),
new clsColor(Color.Aqua, nameof(Color.Aqua)),
new clsColor(Color.Black, nameof(Color.Black)),
new clsColor(Color.Blue, nameof(Color.Blue)),
new clsColor(Color.FromRgb(64f/255,64f/255,64f/255), "Dark Gray"),
new clsColor(Color.Fuchsia, nameof(Color.Fuchsia)),
new clsColor(Color.Gray, nameof(Color.Gray)),
new clsColor(Color.Green, nameof(Color.Green)),
new clsColor(Color.Lime, nameof(Color.Lime)),
new clsColor(Color.Maroon, nameof(Color.Maroon)),
new clsColor(Color.Navy, nameof(Color.Navy)),
new clsColor(Color.Olive, nameof(Color.Olive)),
new clsColor(Color.Pink, nameof(Color.Pink)),
new clsColor(Color.Purple, nameof(Color.Purple)),
new clsColor(Color.Red, nameof(Color.Red)),
new clsColor(Color.Silver, nameof(Color.Silver)),
new clsColor(Color.Teal, nameof(Color.Teal)),
new clsColor(Color.White, nameof(Color.White)),
new clsColor(Color.Yellow, nameof(Color.Yellow))
};
for(int i = 0; i < 10; i++)
{
Color c = Color.FromRgb(rand.NextDouble(), rand.NextDouble(), rand.NextDouble());
colors.Add(new clsColor(c, null));
}
return colors;
}
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<!--MasterDetailPage.xaml-->
<MasterDetailPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:HelloXamarinForms"
x:Class="HelloXamarinForms.MasterDetailPageXaml"
IsPresented="True">
<MasterDetailPage.Master>
<ContentPage Title="Colors">
<ContentPage.Padding>
<OnPlatform x:TypeArguments="Thickness" iOS="0, 20, 0, 0" />
</ContentPage.Padding>
<StackLayout>
<ListView x:Name="listView"
ItemsSource="{x:Static local:clsColors.GetColors}"
ItemTapped="OnListViewItemTap">
<ListView.ItemTemplate>
<DataTemplate>
<TextCell Text="{Binding Name}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage>
</MasterDetailPage.Master>
<MasterDetailPage.Detail>
<NavigationPage>
<x:Arguments>
<!--Notice the BindingContext of the ContentPage-->
<ContentPage Title="{Binding Name}"
BindingContext="{Binding Source={x:Reference listView}, Path=SelectedItem}">
<StackLayout>
<StackLayout HorizontalOptions="Center" Spacing="0">
<StackLayout.Resources>
<ResourceDictionary>
<Style TargetType="Label">
<Setter Property="FontSize" Value="Large" />
<Setter Property="FontAttributes" Value="Bold" />
</Style>
</ResourceDictionary>
</StackLayout.Resources>
<Label Text="{Binding Hex, StringFormat='#{0}'}" />
<Label Text="{Binding Rgb, StringFormat='RGB: {0}'}" />
</StackLayout>
<Frame>
<BoxView Color="{Binding Color}" />
</Frame>
</StackLayout>
</ContentPage>
</x:Arguments>
</NavigationPage>
</MasterDetailPage.Detail>
</MasterDetailPage>
When a ListView
item is tapped, hide the master page.
// MasterDetailPage.xaml.cs
using Xamarin.Forms;
namespace HelloXamarinForms
{
public partial class MasterDetailPageXaml : MasterDetailPage
{
public MasterDetailPageXaml()
{
InitializeComponent();
}
void OnListViewItemTap(object sender, ItemTappedEventArgs args)
{
// This will hide the master page
IsPresented = false;
}
}
}