Navigation hiérarchique
La classe NavigationPage propose une expérience de navigation hiérarchique où l’utilisateur est en mesure de parcourir les pages, vers l’avant et vers l’arrière, comme il le souhaite. La classe implémente la navigation sous forme de pile LIFO (dernier entré, premier sorti) d’objets Pages. Cet article montre comment utiliser la classe NavigationPage pour effectuer la navigation dans une pile de pages.
Pour passer d’une page à une autre, une application envoie une nouvelle page dans la pile de navigation, où elle devient la page active, comme illustré dans le diagramme suivant :
Pour revenir à la page précédente, l’application dépile la page actuelle, et la nouvelle page tout en haut devient la page active, comme illustré dans le diagramme suivant :
Les méthodes de navigation sont exposées par la propriété Navigation
sur n’importe quel type dérivé Page
. Ces méthodes permettent d’envoyer des pages dans la pile de navigation, de retirer des pages de la pile de navigation, et d’effectuer des manipulations de la pile.
Navigation
Dans la navigation hiérarchique, la classe NavigationPage
est utilisée pour parcourir une pile d’objets ContentPage
. Les captures d’écran suivantes montrent les principaux composants de NavigationPage
sur chaque plateforme :
La disposition d’une NavigationPage
dépend de la plateforme :
- Sur iOS, une barre de navigation est présente en haut de la page et affiche un titre, avec un bouton Précédent permettant de revenir à la page précédente.
- Sur Android, une barre de navigation est présente en haut de la page et affiche un titre, une icône et un bouton Précédent permettant de revenir à la page précédente. L’icône est définie dans l’attribut
[Activity]
qui décore la classeMainActivity
dans le projet propre à la plateforme Android. - Sur la plateforme Windows universelle, une barre de navigation en haut de la page affiche un titre.
Sur toutes les plateformes, la valeur de la propriété Page.Title
est affichée en tant que titre de la page. En outre, la IconColor
propriété peut être définie sur une Color
valeur appliquée à l’icône dans la barre de navigation.
Remarque
Nous vous recommandons de remplir une NavigationPage
uniquement avec des instances de ContentPage
.
Création de la page racine
La première page ajoutée à une pile de navigation est appelée la page racine de l’application et l’exemple de code suivant illustre le déroulement de l’opération :
public App ()
{
MainPage = new NavigationPage (new Page1Xaml ());
}
Cela entraîne l’envoi (push) de l’instance Page1Xaml
ContentPage
sur la pile de navigation, où elle devient la page active et la page racine de l’application. Ceci est illustré dans les captures d’écran suivantes :
Remarque
La propriété RootPage
d’une instance de NavigationPage
permet d’accéder à la première page de la pile de navigation.
Envoi de pages dans la pile de navigation
Pour accéder à Page2Xaml
, vous devez appeler la méthode PushAsync
sur la propriété Navigation
de la page active, comme illustré dans l’exemple de code suivant :
async void OnNextPageButtonClicked (object sender, EventArgs e)
{
await Navigation.PushAsync (new Page2Xaml ());
}
L’instance de Page2Xaml
est ainsi envoyée dans la pile de navigation, où elle devient la page active. Ceci est illustré dans les captures d’écran suivantes :
Quand la méthode PushAsync
est appelée, les événements suivants se produisent :
- La substitution
OnDisappearing
de la page qui appellePushAsync
est appelée. - La substitution
OnAppearing
de la page cible de la navigation est appelée. - La tâche
PushAsync
est effectuée.
Toutefois, l’ordre exact dans lequel ces événements se produisent dépend de la plateforme. Pour plus d’informations, consultez le chapitre 24 du livre de Xamarin.Forms Charles Petzold.
Remarque
Les appels des substitutions OnDisappearing
et OnAppearing
ne peuvent pas être considérés comme des indications garanties de la navigation entre les pages. Par exemple, sur iOS, la substitution de OnDisappearing
est appelée dans la page active quand l’application se termine.
Retrait de pages de la pile de navigation
La page active peut être retirée de la pile de navigation en appuyant sur le bouton Précédent sur l’appareil, qu’il s’agisse d’un bouton physique sur l’appareil ou d’un bouton à l’écran.
Pour revenir par programmation à la page d’origine, l’instance de Page2Xaml
doit appeler la méthode PopAsync
, comme illustré dans l’exemple de code suivant :
async void OnPreviousPageButtonClicked (object sender, EventArgs e)
{
await Navigation.PopAsync ();
}
L’instance de Page2Xaml
est ainsi retirée de la pile de navigation, et la nouvelle page tout en haut devient la page active. Quand la méthode PopAsync
est appelée, les événements suivants se produisent :
- La substitution
OnDisappearing
de la page qui appellePopAsync
est appelée. - La substitution
OnAppearing
de la page cible de la navigation est appelée. - La tâche
PopAsync
est terminée.
Toutefois, l’ordre exact dans lequel ces événements se produisent dépend de la plateforme. Pour plus d’informations, consultez le chapitre 24 du livre de Xamarin.Forms Charles Petzold.
En plus des méthodes PushAsync
et PopAsync
, la propriété Navigation
de chaque page fournit également une méthode PopToRootAsync
, illustrée dans l’exemple de code suivant :
async void OnRootPageButtonClicked (object sender, EventArgs e)
{
await Navigation.PopToRootAsync ();
}
Cette méthode retire de la pile de navigation toutes les pages sauf la Page
racine, ce qui fait de la page racine de l’application la page active.
Animation des transitions de page
La propriété Navigation
de chaque page fournit également des méthodes d’envoi et de dépilation substituées qui incluent un paramètre boolean
contrôlant l’affichage d’une animation de page durant la navigation, comme indiqué dans l’exemple de code suivant :
async void OnNextPageButtonClicked (object sender, EventArgs e)
{
// Page appearance not animated
await Navigation.PushAsync (new Page2Xaml (), false);
}
async void OnPreviousPageButtonClicked (object sender, EventArgs e)
{
// Page appearance not animated
await Navigation.PopAsync (false);
}
async void OnRootPageButtonClicked (object sender, EventArgs e)
{
// Page appearance not animated
await Navigation.PopToRootAsync (false);
}
Si vous affectez au paramètre boolean
la valeur false
, l’animation de transition de page est désactivée. En revanche, si vous affectez au paramètre la valeur true
l’animation de transition de page est activée, à condition qu’elle soit prise en charge par la plateforme sous-jacente. Toutefois, les méthodes d’envoi et de dépilation qui n’ont pas ce paramètre activent l’animation par défaut.
Passage des données durant la navigation
Il est parfois nécessaire qu’une page passe des données à une autre page durant la navigation. Il existe pour cela deux techniques : transmettre les données par le biais d’un constructeur de page, et définir les données comme BindingContext
de la nouvelle page. Nous allons maintenant examiner chacune de ces techniques.
Passage des données via un constructeur de page
La technique la plus simple pour passer des données à une autre page durant la navigation consiste à utiliser un paramètre de constructeur de page, comme indiqué dans l’exemple de code suivant :
public App ()
{
MainPage = new NavigationPage (new MainPage (DateTime.Now.ToString ("u")));
}
Ce code crée une instance de MainPage
et transmet la date et l’heure actuelles au format ISO8601, encapsulées dans une instance de NavigationPage
.
L’instance de MainPage
reçoit les données par le biais d’un paramètre de constructeur, comme illustré dans l’exemple de code suivant :
public MainPage (string date)
{
InitializeComponent ();
dateLabel.Text = date;
}
Les données sont ensuite affichées dans la page en définissant la propriété Label.Text
, comme indiqué dans les captures d’écran suivantes :
Transmission de données par le biais d’un BindingContext
Il existe une autre approche pour passer des données à une autre page durant la navigation. Elle consiste à affecter les données au BindingContext
de la nouvelle page, comme indiqué dans l’exemple de code suivant :
async void OnNavigateButtonClicked (object sender, EventArgs e)
{
var contact = new Contact {
Name = "Jane Doe",
Age = 30,
Occupation = "Developer",
Country = "USA"
};
var secondPage = new SecondPage ();
secondPage.BindingContext = contact;
await Navigation.PushAsync (secondPage);
}
Ce code affecte au BindingContext
de l’instanceSecondPage
l’instance de Contact
, puis accède à SecondPage
.
SecondPage
utilise ensuite la liaison de données pour afficher les données de l’instance de Contact
, comme indiqué dans l’exemple de code XAML suivant :
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="PassingData.SecondPage"
Title="Second Page">
<ContentPage.Content>
<StackLayout HorizontalOptions="Center" VerticalOptions="Center">
<StackLayout Orientation="Horizontal">
<Label Text="Name:" HorizontalOptions="FillAndExpand" />
<Label Text="{Binding Name}" FontSize="Medium" FontAttributes="Bold" />
</StackLayout>
...
<Button x:Name="navigateButton" Text="Previous Page" Clicked="OnNavigateButtonClicked" />
</StackLayout>
</ContentPage.Content>
</ContentPage>
L’exemple de code suivant montre comment la liaison de données peut être effectuée en C# :
public class SecondPageCS : ContentPage
{
public SecondPageCS ()
{
var nameLabel = new Label {
FontSize = Device.GetNamedSize (NamedSize.Medium, typeof(Label)),
FontAttributes = FontAttributes.Bold
};
nameLabel.SetBinding (Label.TextProperty, "Name");
...
var navigateButton = new Button { Text = "Previous Page" };
navigateButton.Clicked += OnNavigateButtonClicked;
Content = new StackLayout {
HorizontalOptions = LayoutOptions.Center,
VerticalOptions = LayoutOptions.Center,
Children = {
new StackLayout {
Orientation = StackOrientation.Horizontal,
Children = {
new Label{ Text = "Name:", FontSize = Device.GetNamedSize (NamedSize.Medium, typeof(Label)), HorizontalOptions = LayoutOptions.FillAndExpand },
nameLabel
}
},
...
navigateButton
}
};
}
async void OnNavigateButtonClicked (object sender, EventArgs e)
{
await Navigation.PopAsync ();
}
}
Les données sont ensuite affichées dans la page par une série de contrôles Label
, comme indiqué dans les captures d’écran suivantes :
Pour plus d’informations sur la liaison de données, consultez Notions de base de la liaison de données.
Manipulation de la pile de navigation
La propriété Navigation
expose une propriété NavigationStack
à partir de laquelle les pages dans la pile de navigation peuvent être obtenues. Tout en Xamarin.Forms conservant l’accès à la pile de navigation, la Navigation
propriété fournit les méthodes et RemovePage
les InsertPageBefore
méthodes de manipulation de la pile en insérant des pages ou en les supprimant.
La méthode InsertPageBefore
insère une page spécifiée dans la pile de navigation avant une page existante spécifiée, comme indiqué dans le diagramme suivant :
La méthode RemovePage
supprime la page spécifiée de la pile de navigation, comme illustré dans le diagramme suivant :
Ces méthodes permettent de disposer d’une expérience de navigation personnalisée, par exemple remplacer une page de connexion par une nouvelle page, suite à une connexion réussie. L’exemple de code suivant illustre ce scénario :
async void OnLoginButtonClicked (object sender, EventArgs e)
{
...
var isValid = AreCredentialsCorrect (user);
if (isValid) {
App.IsUserLoggedIn = true;
Navigation.InsertPageBefore (new MainPage (), this);
await Navigation.PopAsync ();
} else {
// Login failed
}
}
À condition que les informations d’identification de l’utilisateur soient correctes, l’instance de MainPage
est insérée dans la pile de navigation avant la page active. La méthode PopAsync
supprime ensuite la page active de la pile de navigation, et l’instance de MainPage
devient la page active.
Affichage des vues dans la barre de navigation
Tout Xamarin.FormsView
peut être affiché dans la barre de navigation d’un NavigationPage
. Pour cela, vous devez définir la propriété jointe NavigationPage.TitleView
sur une View
. Cette propriété jointe peut être définie sur n’importe quelle Page
, et quand la Page
envoyée vers sur une NavigationPage
, la NavigationPage
respecte la valeur de la propriété.
L’exemple suivant montre comment définir la NavigationPage.TitleView
propriété jointe à partir de XAML :
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="NavigationPageTitleView.TitleViewPage">
<NavigationPage.TitleView>
<Slider HeightRequest="44" WidthRequest="300" />
</NavigationPage.TitleView>
...
</ContentPage>
Voici le code C# équivalent :
public class TitleViewPage : ContentPage
{
public TitleViewPage()
{
var titleView = new Slider { HeightRequest = 44, WidthRequest = 300 };
NavigationPage.SetTitleView(this, titleView);
...
}
}
Il en résulte l’affichage d’un Slider
dans la barre de navigation dans la NavigationPage
:
Important
De nombreuses vues n’apparaissent dans la barre de navigation que si la taille de la vue est spécifiée avec les propriétés WidthRequest
et HeightRequest
. En guise d’alternative, vous pouvez encapsuler la vue dans un StackLayout
avec des valeurs appropriées affectées aux propriétés HorizontalOptions
et VerticalOptions
.
Notez que, étant donné que la classe Layout
dérive de la classe View
, la propriété jointe TitleView
peut être configurée de façon à afficher une classe de disposition qui contient plusieurs vues. Sur iOS et la plateforme universelle Windows (UWP), la hauteur de la barre de navigation ne peut pas être changée ; ainsi, un découpage se produira si la taille de la vue affichée dans la barre de navigation est supérieure à la taille par défaut de la barre de navigation. En revanche, sur Android, la hauteur de la barre de navigation peut être changée en affectant un double
représentant la nouvelle hauteur comme valeur de la propriété pouvant être liée NavigationPage.BarHeight
. Pour plus d’informations, consultez Définition de la hauteur de la barre de navigation sur une NavigationPage.
En guise d’alternative, une barre de navigation étendue peut être suggérée en plaçant une partie du contenu dans la barre de navigation et une autre partie dans une vue en haut du contenu de page, à laquelle vous affectez une couleur correspondant à celle de la barre de navigation. En outre, sur iOS la ligne de séparation et l’ombre qui se trouve au bas de la barre de navigation peuvent être supprimées en affectant la valeur true
à la propriété pouvant être liée NavigationPage.HideNavigationBarSeparator
. Pour plus d’informations, consultez Masquage du séparateur de barre de navigation sur une NavigationPage.
Remarque
Les propriétés BackButtonTitle
, Title
, TitleIcon
et TitleView
peuvent toutes définir des valeurs qui occupent de l’espace sur la barre de navigation. Bien que la taille de la barre de navigation varie en fonction de la plateforme et de la taille de l’écran, la définition de toutes ces propriétés provoquera des conflits en raison de l’espace limité disponible. Au lieu d’essayer d’utiliser une combinaison de ces propriétés, vous obtiendrez peut-être plus facilement la conception de barre de navigation souhaitée en définissant uniquement la propriété TitleView
.
Limites
Vous devez prendre en compte un certain nombre de limitations lors de l’affichage d’une View
dans la barre de navigation d’une NavigationPage
:
- Sur iOS, les vues placées dans la barre de navigation d’une
NavigationPage
apparaissent dans une position différente selon que les grands titres sont activés ou non. Pour plus d’informations sur l’activation des grands titres, consultez Affichage de grands titres. - Sur Android, vous ne pouvez placer des vues dans la barre de navigation d’une
NavigationPage
que dans les applications qui utilisent app-compat. - Nous vous déconseillons de placer des vues volumineuses et complexes, telles que
ListView
etTableView
, dans la barre de navigation d’uneNavigationPage
.