Dot.Blog

C#, XAML, WinUI, WPF, Android, MAUI, IoT, IA, ChatGPT, Prompt Engineering

Gérer le Z-Index sous MAUI

Si vous travaillez dans .NET MAUI et que vous avez plusieurs contrôles superposés qui doivent être révélés en fonction de certaines conditions, ce qui suit vous aidera sans aucun doute à gérer cette situation.

Le Z-Index

L'ordre dans lequel un élément apparaît sur l'axe z (la profondeur) est représenté par ZIndex , une propriété ajoutée dans .NET MAUI Preview 12 à tous les éléments hérités de l' interface IView. Un contrôle avec une valeur ZIndex plus élevée sera placé au-dessus des autres. Il n’y a pas de valeur spécifique pour un emplacement spécifique, tout est relatif. Par exemple, un contrôle avec ZIndex 0 sera en bas (en-dessous), et un contrôle avec ZIndex 1 ou supérieur sera en haut (au-dessus de ceux d’ordre 0).

Il n’y a pas de petites choses dans MAUI, tout est important, celui qui maîtrise les dernières syntaxes de C# 11 voire 12 ou 13 restera planté comme un idiot devant un problème (simple) d’affichage en plusieurs couches… s’il ne connait pas le Z-Index. La connaissance est un tout et mieux vaut connaître large que de connaître pointu dans des environnements aussi complexes et variés que MAUI Cross-plateforme. 

Je vous propose donc aujourd’hui d’explorer le comportement de ZIndex.

Rendu par défaut

Sous XAML c’est simple, le code est exécuté dans l’ordre dans lequel il est écrit… Donc la création de plusieurs objets dans un même espace va créer un empilement visuel directement lié à l’ordre d’écriture. Le premier objet le plus en arrière, le dernier le plus en avant-plan.

<Grid>
    <Label Text="View 1"  Margin="10,0,0,0" BackgroundColor="Green"
           Style="{StaticResource labelStyle}" />
    <Label Text="View 2" Margin="30,30,0,0" BackgroundColor="Navy"
           Style="{StaticResource labelStyle}"/>
    <Label Text="View 3"  Margin="60,60,0,0" BackgroundColor="Yellow"
           Style="{StaticResource labelStyle}"/>
    <Label Text="View 4"  Margin="90,90,0,0" BackgroundColor="SkyBlue"
           Style="{StaticResource labelStyle}"/>
</Grid> 

Quatre labels créés dans l’ordre d’écriture… ce qui donnera :

 

Rendu utilisant le Z-Index

Dans l'exemple de code suivant, chaque vue est définie avec une valeur ZIndex . Ici, la dernière vue peinte en tant que couche supérieure dans l'exemple précédent est définie avec une valeur ZIndex inférieure à celle des autres vues.

<Grid>
    <Label Text="View 1" ZIndex="4" Margin="10,0,0,0" BackgroundColor="Green"
           Style="{StaticResource labelStyle}" />
    <Label Text="View 2" ZIndex="3" Margin="30,30,0,0" BackgroundColor="Navy"
           Style="{StaticResource labelStyle}"/>
    <Label Text="View 3" ZIndex="2" Margin="60,60,0,0" BackgroundColor="Yellow"
           Style="{StaticResource labelStyle}"/>
    <Label Text="View 4" ZIndex="1" Margin="90,90,0,0" BackgroundColor="SkyBlue"
           Style="{StaticResource labelStyle}"/>
</Grid>         

Les vues sont rendues en fonction des valeurs ZIndex attribuées. Ici, View1 est peinte au-dessus des autres calques car elle a une valeur ZIndex plus élevée.

 

Amenez les vues .NET MAUI au premier plan

Le Z-Index étant une propriété des Views il est légitime de se demander si on peut le manipuler au runtime ce qui permettrait de faire passer au premier plan (ou à l’arrière plan ou n’importe où entre les deux) des Views selon les besoins afin de rendre l’UX plus agréable.         

Dans l'exemple de code suivant, chaque vue est définie avec une valeur ZIndex lors du chargement initial.

<Grid>
    <Label x:Name="view1" Text="View 1" ZIndex="4" Margin="10,0,0,0"
           BackgroundColor="Green" Style="{StaticResource labelStyle}" >
           <Label.GestureRecognizers>
            <TapGestureRecognizer Command="{Binding BringToFront}"
                       CommandParameter="{Binding Source={x:Reference view1}}"/>
           </Label.GestureRecognizers>
    </Label>
    <Label x:Name="view2" Text="View 2" ZIndex="3" Margin="30,30,0,0"
           BackgroundColor="Navy" Style="{StaticResource labelStyle}">
           <Label.GestureRecognizers>
            <TapGestureRecognizer Command="{Binding BringToFront}"
                       CommandParameter="{Binding Source={x:Reference view2}}"/>
           </Label.GestureRecognizers>
    </Label>
    <Label x:Name="view3" Text="View 3" ZIndex="2" Margin="60,60,0,0"
           BackgroundColor="Yellow" Style="{StaticResource labelStyle}">
           <Label.GestureRecognizers>
            <TapGestureRecognizer Command="{Binding BringToFront}"
                       CommandParameter="{Binding Source={x:Reference view3}}"/>
           </Label.GestureRecognizers>
    </Label>
    <Label x:Name="view4" Text="View 4" ZIndex="1" Margin="90,90,0,0" 
           BackgroundColor="SkyBlue" Style="{StaticResource labelStyle}">
          <Label.GestureRecognizers>
            <TapGestureRecognizer Command="{Binding BringToFront}" 
                       CommandParameter="{Binding Source={x:Reference view4}}"/>
          </Label.GestureRecognizers>
    </Label>
</Grid>

Maintenant, nous allons mettre à jour dynamiquement la valeur ZIndex des vues au runtime. Ici, nous choisissons de mettre la vue au premier plan en fonction de l'action d’un TapGesture. Ce qu’illustre le code suivant.

private async void OnBringToFrontAsync(object view)
{
    var viewName = (view as Label).Text;
    bool answer = await Application.Current.MainPage.DisplayAlert(
              "Bring to front", "Je suis la vue "+viewName + " , " + 
              "Dois-je venir en avant-plan ?", "Oui", "Non");
    if (answer)
    {
        (view as Label).ZIndex = Zindex;
        Zindex += 1;
    }
}

Le résultat visuel d’un test de ce code peut être vu dans l’animation ci-dessous.


Conclusion

La manipulation du Z-Index n’est pas une nouveauté MAUI, XAML sait le faire depuis WPF, mais sa manipulation sous les Xamarin.Forms par exemple n’existait pas, il fallait utiliser deux méthodes des Vues, RaiseChild() and LowerChild(), ce qui n’a rien à voir avec la manipulation d’une propriété (éventuellement bindée). MAUI restaure ce fonctionnement de XAML comme beaucoup d’autres afin que le « faux » XAML des Xamarin.Forms rentre progressivement dans le rang des « vrais » XAML écrit par Microsoft.

Le Z-Index n’est certes pas une fonctionnalité killer, mais elle est précieuse pour le développement des UI et encore plus lorsqu’on utilise avec intelligence de façon dynamique pour améliorer l’UX.

En tout cas, le XAML MAUI sait le faire, comme plein d’autres choses, et c’est vraiment bien.

Stay Tuned !


Faites des heureux, partagez l'article !
blog comments powered by Disqus