Quelle est la différence entre les LayoutOptions de Xamarin.Form, en particulier Fill et Expand?

170

Dans Xamarin.Forms, chacun Viewa les deux propriétés HorizontalOptionset VerticalOptions. Les deux sont de type LayoutOptionset peuvent avoir l'une des valeurs suivantes:

  • LayoutOptions.Start
  • LayoutOptions.Center
  • LayoutOptions.End
  • LayoutOptions.Fill
  • LayoutOptions.StartAndExpand
  • LayoutOptions.CenterAndExpand
  • LayoutOptions.EndAndExpand
  • LayoutOptions.FillAndExpand

Apparemment, il contrôle l'alignement de la vue sur la vue parent. Mais quel est exactement le comportement de chaque option individuelle? Et quelle est la différence entre Fillet le suffixe Expand?

Falko
la source

Réponses:

335

Réponse courte

Start, Center, EndEt Filldéfinir de la vue de l' alignement dans son espace .

Expanddéfinit s'il occupe plus d'espace s'il est disponible.

Théorie

La structure LayoutOptionscontrôle deux comportements distincts:

  1. Alignement: comment la vue est-elle alignée dans la vue parent?

    • Start: Pour l'alignement vertical, la vue est déplacée vers le haut. Pour l'alignement horizontal, il s'agit généralement du côté gauche. (Mais notez que sur les appareils avec un réglage de langue de droite à gauche, c'est l'inverse, c'est-à-dire aligné à droite.)
    • Center: La vue est centrée.
    • End: La vue est généralement alignée en bas ou à droite. (Dans les langues de droite à gauche, bien sûr, aligné à gauche.)
    • Fill: Cet alignement est légèrement différent. La vue s'étendra sur toute la taille de la vue parent.

    Si le parent, cependant, n'est pas plus grand que ses enfants, vous ne remarquerez aucune différence entre ces alignements. L'alignement n'a d'importance que pour les vues parent avec un espace supplémentaire disponible.

  2. Expansion: l'élément occupera-t-il plus d'espace s'il est disponible?

    • Suffixe Expand: Si la vue parente est plus grande que la taille combinée de tous ses enfants, c'est-à-dire qu'un espace supplémentaire est disponible, alors l'espace est proportionné entre les vues enfants avec ce suffixe. Ces enfants «occuperont» leur espace, mais ne le «rempliront» pas nécessairement. Nous examinerons ce comportement dans l'exemple ci-dessous.
    • Pas de suffixe: les enfants sans Expandsuffixe n'obtiendront pas d'espace supplémentaire, même si plus d'espace est disponible.

    Encore une fois, si la vue parente n'est pas plus grande que ses enfants, le suffixe d'extension ne fait pas non plus de différence.

Exemple

Jetons un œil à l'exemple suivant pour voir la différence entre les huit options de mise en page.

L'application contient un gris foncé StackLayoutavec huit boutons blancs imbriqués, chacun d'eux étant étiqueté avec son option de disposition verticale. En cliquant sur l'un des boutons, il assigne son option de disposition verticale à la disposition de la pile. De cette façon, nous pouvons facilement tester l'interaction des vues avec les parents, les deux avec une option de mise en page différente.

(Les dernières lignes de code ajoutent des cases jaunes supplémentaires. Nous y reviendrons dans un instant.)

public static class App
{
    static readonly StackLayout stackLayout = new StackLayout {
        BackgroundColor = Color.Gray,
        VerticalOptions = LayoutOptions.Start,
        Spacing = 2,
        Padding = 2,
    };

    public static Page GetMainPage()
    {
        AddButton("Start", LayoutOptions.Start);
        AddButton("Center", LayoutOptions.Center);
        AddButton("End", LayoutOptions.End);
        AddButton("Fill", LayoutOptions.Fill);
        AddButton("StartAndExpand", LayoutOptions.StartAndExpand);
        AddButton("CenterAndExpand", LayoutOptions.CenterAndExpand);
        AddButton("EndAndExpand", LayoutOptions.EndAndExpand);
        AddButton("FillAndExpand", LayoutOptions.FillAndExpand);

        return new NavigationPage(new ContentPage {
            Content = stackLayout,
        });
    }

    static void AddButton(string text, LayoutOptions verticalOptions)
    {
        stackLayout.Children.Add(new Button {
            Text = text,
            BackgroundColor = Color.White,
            VerticalOptions = verticalOptions,
            HeightRequest = 20,
            Command = new Command(() => {
                stackLayout.VerticalOptions = verticalOptions;
                (stackLayout.ParentView as Page).Title = "StackLayout: " + text;
            }),
        });
        stackLayout.Children.Add(new BoxView {
            HeightRequest = 1,
            Color = Color.Yellow,
        });
    }
}

Les captures d'écran suivantes montrent le résultat en cliquant sur chacun des huit boutons. Nous faisons les observations suivantes:

  • Tant que le parent stackLayoutest serré (pas Fillla page), l'option de mise en page verticale de chacun Buttonest négligeable.
  • L'option de disposition verticale n'a d'importance que si le stackLayoutest plus grand (par exemple via l' Fillalignement) et que les boutons individuels ont le Expandsuffixe.
  • L'espace supplémentaire est éventuellement proportionné entre tous les boutons avec Expandsuffixe. Pour voir cela plus clairement, nous avons ajouté des lignes horizontales jaunes entre tous les deux boutons voisins.
  • Les boutons avec plus d'espace que leur hauteur demandée ne le «remplissent» pas nécessairement. Dans ce cas, le comportement réel est contrôlé par leur alignement. Par exemple, ils sont soit alignés en haut, au centre ou en bouton de leur espace, soit le remplissent complètement.
  • Tous les boutons s'étendent sur toute la largeur de la mise en page, car nous ne modifions que le VerticalOptions.

Captures d'écran

Vous trouverez ici les captures d'écran haute résolution correspondantes.

Falko
la source
6
l'image ressemble à [[midfing]], lol. je plaisante, c'était vraiment utile
Joy Rex
1
@JoyRex: Eh bien, peut - être que cette version est un peu moins déroutante. ;)
Falko
2
J'ai confondu avec la sortie ci-dessus. start & startAndExpand sont tous deux identiques. Quelle est la différence entre ceux-ci? pouvez-vous donner une explication si possible ..
Ranjith Kumar
1
FillAndExpandest ce que vous voulez, 99% pour le temps
Stephane Delcroix
1
@RanjithKumar Ils sont pareils. Si StackLayout était imbriqué dans un autre parent, son FillAndExpand pourrait faire une différence - il se développerait dans son parent.
Miha Markic
16

Il existe un petit bogue dans la version actuelle de Xamarin.Forms; peut-être que cela fait un moment.

CenterAndExpand ne se développe généralement pas et contourner ce problème peut être déroutant.

Par exemple, si vous avez StackLayoutdéfini sur CenterAndExpand, vous placez une étiquette à l'intérieur qui est également définie sur CenterAndExpandvous attendez une étiquette qui est pleine largeur du StackLayout. Nan. Cela ne se développera pas. Vous devez définir le StackLayoutsur " FillAndExpand" pour que l'objet Label imbriqué s'étende sur toute la largeur du StackLayout, puis indiquez à Label de centrer le texte, pas lui-même en tant qu'objet, avec HorizontalTextAlignment="Center". D'après mon expérience, vous devez définir à la fois le parent et l'enfant imbriqué FillAndExpandsi vous voulez vraiment vous assurer qu'il se développe pour s'adapter.

        <StackLayout HorizontalOptions="FillAndExpand"
                     Orientation="Vertical"
                     WidthRequest="300">
            <Label BackgroundColor="{StaticResource TileAlerts}"
                   HorizontalOptions="FillAndExpand"
                   Style="{StaticResource LabelStyleReversedLrg}"
                   HorizontalTextAlignment="Center"
                   Text="Alerts" />
Clint StLaurent
la source
3
"... vous vous attendriez à une étiquette qui soit sur toute la largeur du StackLayout." Cette hypothèse est incorrecte. Expandest uniquement utilisé pour les enfants de StackLayout. Donc, si votre StackLayout est la racine, ou pas dans un autre StackLayout, cela Expandn'a aucun effet. Au lieu de cela, toute option autre que Fill agirait comme un "contenu enveloppant" pour le dimensionnement, ce que vous voyez.
therealjohn
De plus, l'expansion ne fonctionne que pour les LayoutOptions qui ont la même orientation que StackLayout. Dans ce cas, la mise en page est "Vertical", mais les options en question sont Horizontales (opposées).
therealjohn
Le terme «AndExpand» est ambigu. Il pourrait être interprété comme «élargir autant que possible» ou «étendre seulement autant que nécessaire». Je pense que Microsoft devrait changer les termes en quelque chose de moins déroutant, comme "CenterAndExpandToParent" ou "CenterAndExpandAsNeeded"
technoman23
1

Falko a donné une bonne explication, mais je voulais ajouter à cela avec un autre visuel et comment ces balises fonctionnent en xaml, ce que je préfère utiliser la plupart du temps. J'ai fait un projet simple pour tester les résultats d'affichage. Voici le Xaml de la page principale:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="Alignments.MainPage"
             BackgroundColor="White">


    <StackLayout HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" BackgroundColor="LightGray" Padding="1" Margin="30">
        <Label Text="Vert: EndAndExpand, Horz: EndAndExpand" VerticalOptions="EndAndExpand" HorizontalOptions="EndAndExpand" BackgroundColor="White"/>
    </StackLayout>


</ContentPage>

Comme vous pouvez le voir, c'est un StackLayout très simple avec une étiquette à l'intérieur. Pour chaque image ci-dessous, j'ai gardé le StackLayout le même, j'ai juste changé les options horizontales et verticales pour l'entrée et changé le texte pour afficher les options sélectionnées, afin que vous puissiez voir comment l'entrée se déplace et se redimensionne.

Démarrer vs StartAndExpand Voici le code utilisé pour démarrer:

<Label Text="Vert: Start, Horz: Start" VerticalOptions="Start" HorizontalOptions="Start" BackgroundColor="White"/>

Et le code utilisé pour StartAndExpand:

<Label Text="Vert: StartAndExpand, Horz: StartAndExpand" VerticalOptions="StartAndExpand" HorizontalOptions="StartAndExpand" BackgroundColor="White"/>

Comme vous pouvez le voir, il n'y a aucune différence visuellement autre que le texte utilisé dans l'option StartAndExpand. Cela a été testé sur mon appareil physique Samsung A30. Ceux-ci peuvent s'afficher différemment sur différents appareils, mais je pense que toutes les images ici montrent collectivement qu'il existe des bogues dans Xamarin. Pour le reste, je vais juste montrer les captures d'écran, je pense qu'elles sont explicites.

End vs EndAndExpand

Centre vs CenterAndExpand

Fill vs FillAndExpand

Je recommande également de consulter la documentation Microsoft pour obtenir des détails supplémentaires. Il est à noter que "L'expansion est utilisée uniquement par un StackLayout".

technoman23
la source
Belle visualisation. Mais je ne vois pas pourquoi cela devrait afficher des bogues dans Xamarin. Ce qui peut prêter à confusion, c'est que les étiquettes peuvent occuper plus d'espace que leur fond blanc (les zones grises dans mon exemple). Ainsi, une étiquette "Centre Vert" est centrée dans l'espace qu'elle occupe - pas dans toute la page. Apparemment, après presque six ans, ce sujet est toujours aussi déroutant qu'il l'était auparavant.
Falko