Jaka jest różnica między LayoutOptions platformy Xamarin.Form, zwłaszcza Fill and Expand?

170

W Xamarin.Forms każdy Viewma dwie właściwości HorizontalOptionsi VerticalOptions. Oba są typu LayoutOptionsi mogą mieć jedną z następujących wartości:

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

Najwyraźniej kontroluje wyrównanie widoku w widoku macierzystym. Ale jak dokładnie wygląda zachowanie poszczególnych opcji? Jaka jest różnica między Fillsufiksem a Expand?

Falko
źródło

Odpowiedzi:

335

Krótka odpowiedź

Start, Center, EndI Fillokreślić widoku za wyrównanie w jego przestrzeni .

Expandokreśla, czy zajmuje więcej miejsca, jeśli jest dostępne.

Teoria

Struktura LayoutOptionskontroluje dwa różne zachowania:

  1. Wyrównanie: w jaki sposób widok jest wyrównany w widoku nadrzędnym?

    • Start: W przypadku wyrównania w pionie widok jest przenoszony na górę. W przypadku wyrównania poziomego jest to zwykle lewa strona. (Pamiętaj jednak, że na urządzeniach z ustawieniem języka od prawej do lewej jest odwrotnie, tj. Wyrównanie do prawej).
    • Center: Widok jest wyśrodkowany.
    • End: Zwykle widok jest wyrównany do dołu lub do prawej. (Oczywiście w językach zapisywanych od prawej do lewej z wyrównaniem do lewej).
    • Fill: To wyrównanie jest nieco inne. Widok rozciąga się na cały rozmiar widoku macierzystego.

    Jeśli jednak rodzic nie jest większy niż jego dzieci, nie zauważysz żadnej różnicy między tymi wyrównaniami. Wyrównanie ma znaczenie tylko w przypadku widoków nadrzędnych z dostępną dodatkową przestrzenią.

  2. Rozszerzenie: czy element zajmie więcej miejsca, jeśli będzie dostępny?

    • Przyrostek Expand: jeśli widok nadrzędny jest większy niż łączny rozmiar wszystkich jego elementów podrzędnych, tj. Dostępna jest dodatkowa przestrzeń, wówczas przestrzeń jest proporcjonalna do widoków potomnych z tym przyrostkiem. Te dzieci „zajmą” swoją przestrzeń, ale niekoniecznie ją „wypełnią”. Przyjrzymy się temu zachowaniu w poniższym przykładzie.
    • Bez przyrostka: dzieci bez Expandprzyrostka nie otrzymają dodatkowej przestrzeni, nawet jeśli jest więcej miejsca.

    Ponownie, jeśli widok nadrzędny nie jest większy niż jego dzieci, przyrostek rozwinięcia również nie robi żadnej różnicy.

Przykład

Spójrzmy na poniższy przykład, aby zobaczyć różnicę między wszystkimi ośmioma opcjami układu.

Aplikacja zawiera ciemnoszary StackLayoutz ośmioma zagnieżdżonymi białymi przyciskami, z których każdy jest oznaczony opcją układu pionowego. Po kliknięciu jednego z przycisków przypisuje opcję układu pionowego do układu stosu. W ten sposób możemy łatwo przetestować interakcję widoków z rodzicami, zarówno z różnymi opcjami układu.

(W ostatnich kilku wierszach kodu pojawiają się dodatkowe żółte pola. Wrócimy do tego za chwilę).

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,
        });
    }
}

Poniższe zrzuty ekranu pokazują wynik po kliknięciu każdego z ośmiu przycisków. Dokonujemy następujących obserwacji:

  • Dopóki rodzic stackLayoutjest ciasny (nie ma Fillstrony), opcja układu pionowego każdego z nich Buttonjest pomijalna.
  • Opcja układu pionowego ma znaczenie tylko wtedy, gdy stackLayoutjest większy (np. Przez Fillwyrównanie), a poszczególne przyciski mają Expandsufiks.
  • Dodatkowa przestrzeń jest wyraźnie proporcjonalna wśród wszystkich przycisków z Expandprzyrostkiem. Aby to lepiej zobaczyć, dodaliśmy żółte poziome linie między każdymi dwoma sąsiednimi przyciskami.
  • Przyciski z większą przestrzenią niż żądana wysokość niekoniecznie ją „wypełniają”. W tym przypadku faktyczne zachowanie jest kontrolowane przez ich wyrównanie. Np. Są wyrównane na górze, na środku lub na przycisku swojej przestrzeni lub całkowicie ją wypełniają.
  • Wszystkie przyciski obejmują całą szerokość układu, ponieważ modyfikujemy tylko VerticalOptions.

Zrzuty ekranu

Tutaj znajdziesz odpowiednie zrzuty ekranu w wysokiej rozdzielczości.

Falko
źródło
6
obraz wygląda jak [[midfing]], lol. żartowałem, że to było naprawdę pomocne
Joy Rex
1
@JoyRex: Cóż, może ta wersja jest nieco mniej zagmatwana. ;)
Falko
2
Myliłem się z powyższym wyjściem. start i startAndExpand oba są tym samym wyjściem .. Jaka jest różnica między nimi? czy możesz podać wyjaśnienie, jeśli to możliwe ...
Ranjith Kumar,
1
FillAndExpandjest tym, czego chcesz, 99% czasu
Stephane Delcroix,
1
@RanjithKumar Są takie same. Jeśli StackLayout został zagnieżdżony w innym obiekcie nadrzędnym, jego FillAndExpand może mieć znaczenie - rozwinąłby się w jego nadrzędnym.
Miha Markic
16

W bieżącej wersji Xamarin.Forms jest trochę błąd; może było tam jakiś czas.

CenterAndExpand generalnie nie rozszerza się, a obchodzenie się z nim może być mylące.

Na przykład, jeśli masz StackLayoutustawioną na CenterAndExpand, to umieścisz wewnątrz etykietę, która również jest ustawiona na, CenterAndExpandmożesz oczekiwać etykiety o pełnej szerokości StackLayout. Nie. Nie rozszerzy się. Musisz ustawić wartość StackLayoutna „ FillAndExpand”, aby zagnieżdżony obiekt Label rozszerzył się do pełnej szerokości StackLayout, a następnie powiedzieć etykiecie, aby wyśrodkowała tekst, a nie siebie jako obiekt HorizontalTextAlignment="Center". Z mojego doświadczenia FillAndExpandwynika, że ​​musisz ustawić zarówno rodzica, jak i zagnieżdżone dziecko, jeśli naprawdę chcesz mieć pewność, że rozszerzy się, aby pasowało.

        <StackLayout HorizontalOptions="FillAndExpand"
                     Orientation="Vertical"
                     WidthRequest="300">
            <Label BackgroundColor="{StaticResource TileAlerts}"
                   HorizontalOptions="FillAndExpand"
                   Style="{StaticResource LabelStyleReversedLrg}"
                   HorizontalTextAlignment="Center"
                   Text="Alerts" />
Clint StLaurent
źródło
3
„... można się spodziewać etykiety o pełnej szerokości StackLayout”. To założenie jest błędne. Expandjest używany tylko dla elementów podrzędnych StackLayout. Tak więc, jeśli Twój StackLayout jest katalogiem głównym lub nie znajduje się w innym StackLayout, Expandnie ma to wpływu. Zamiast tego każda opcja inna niż Wypełnij działałaby jak „zawijanie treści” do zmiany rozmiaru, co widzisz.
therealjohn,
Ponadto rozszerzenie działa tylko dla LayoutOptions, które mają tę samą orientację co StackLayout. W tym przypadku układ jest „Pionowy”, ale omawiane opcje to Poziomy (przeciwieństwa).
therealjohn
Termin „AndExpand” jest niejednoznaczny. Można to interpretować jako „rozszerzaj tak bardzo, jak to możliwe” lub „rozszerzaj tylko tak bardzo, jak potrzeba”. Myślę, że Microsoft powinien zmienić warunki na mniej zagmatwane, na przykład „CenterAndExpandToParent” lub „CenterAndExpandAsNeeded”
technoman23
1

Falko podał dobre wyjaśnienie, ale chciałem dodać do tego kolejną wizualizację i sposób działania tych tagów w XAML, czego wolę używać przez większość czasu. Zrobiłem prosty projekt do testowania wyników wyświetlania. Oto Xaml dla strony głównej:

<?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>

Jak widać, jest to bardzo prosty układ StackLayout z etykietą w środku. Dla każdego poniższego obrazu zachowałem ten sam układ StackLayout, po prostu zmieniłem opcje poziome i pionowe wpisu i zmieniłem tekst, aby pokazać wybrane opcje, abyś mógł zobaczyć, jak Entry się porusza i zmienia rozmiar.

Start vs StartAndExpand Oto kod używany do uruchomienia:

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

Oraz kod używany do StartAndExpand:

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

Jak widać, wizualnie nie ma różnicy, poza tym, że w opcji StartAndExpand użyto więcej tekstu. Zostało to przetestowane na moim fizycznym urządzeniu Samsung A30. Mogą one wyświetlać się inaczej na różnych urządzeniach, ale myślę, że wszystkie obrazy tutaj razem pokazują, że w oprogramowaniu Xamarin są błędy. Resztę pokażę tylko zrzuty ekranu, myślę, że są zrozumiałe.

End vs EndAndExpand

Center vs CenterAndExpand

Fill vs FillAndExpand

Polecam również zajrzeć do dokumentacji firmy Microsoft, aby uzyskać dodatkowe informacje. Godne uwagi jest to, że „Expansion jest używany tylko przez StackLayout”.

technoman23
źródło
Ładna wizualizacja. Ale nie rozumiem, dlaczego to powinno pokazywać błędy w oprogramowaniu Xamarin. Mylące może być to, że etykiety mogą zajmować więcej miejsca niż ich białe tło (szare regiony w moim przykładzie). Tak więc etykieta „Vert Center” jest wyśrodkowana na zajmowanym obszarze, a nie na całej stronie. Wygląda na to, że po prawie sześciu latach ten temat jest nadal tak zagmatwany, jak dawniej.
Falko