В чем разница между LayoutOptions Xamarin.Form, особенно Fill и Expand?

170

В Xamarin.Forms каждый Viewимеет два свойства HorizontalOptionsи VerticalOptions. Оба имеют тип LayoutOptionsи могут иметь одно из следующих значений:

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

По-видимому, он контролирует выравнивание представления в родительском представлении. Но как именно поведение каждого отдельного варианта? И в чем разница между Fillсуффиксом и Expand?

Фалько
источник

Ответы:

335

Короткий ответ

Start, Center, EndИ Fillопределить вид по согласованности в ее пространстве .

Expandопределяет , занимает ли он больше места, если доступно.

теория

Структура LayoutOptionsконтролирует два различных поведения:

  1. Выравнивание. Как выравнивается представление в родительском представлении?

    • Start: Для вертикального выравнивания вид перемещается вверх. Для горизонтального выравнивания это обычно левая сторона. (Но обратите внимание, что на устройствах с настройкой языка справа налево это наоборот, то есть выровнено по правому краю.)
    • Center: Вид в центре.
    • End: Обычно вид выровнен снизу или справа. (На языках справа налево, конечно, выравнивание по левому краю.)
    • Fill: Это выравнивание немного отличается. Представление будет растянуто на весь размер родительского представления.

    Если родитель, однако, не больше своих потомков, вы не заметите никакой разницы между этими выравниваниями. Выравнивание имеет значение только для родительских представлений с доступным дополнительным пространством.

  2. Расширение: Будет ли элемент занимать больше места, если доступно?

    • Суффикс Expand: если родительское представление больше, чем объединенный размер всех его дочерних элементов, то есть доступно дополнительное пространство, тогда пространство пропорционально среди дочерних представлений с этим суффиксом. Эти дети будут «занимать» свое пространство, но не обязательно «заполнять» его. Мы рассмотрим это поведение в следующем примере.
    • Без суффикса: дети без Expandсуффикса не получат дополнительное пространство, даже если доступно больше места.

    Опять же, если родительское представление не больше, чем его дочерние элементы, суффикс расширения также не имеет значения.

пример

Давайте посмотрим на следующий пример, чтобы увидеть разницу между всеми восемью вариантами макета.

Приложение содержит темно-серый StackLayoutс восемью вложенными белыми кнопками, каждая из которых имеет свой вариант вертикальной компоновки. При нажатии на одну из кнопок она назначает свой вариант вертикальной компоновки макету стека. Таким образом, мы можем легко протестировать взаимодействие представлений с родителями, с различными вариантами макета.

(Последние несколько строк кода добавляют дополнительные желтые поля. Мы вернемся к этому через минуту.)

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

На следующих снимках экрана показан результат при нажатии на каждую из восьми кнопок. Мы делаем следующие наблюдения:

  • Пока родитель stackLayoutограничен (не Fillстраница), вариант вертикальной разметки каждого Buttonпренебрежимо мал.
  • Параметр вертикальной компоновки имеет значение только в том случае, если stackLayoutон больше (например, посредством Fillвыравнивания), а отдельные кнопки имеют Expandсуффикс.
  • Дополнительное пространство пропорционально распределяется между всеми кнопками с Expandсуффиксом. Чтобы увидеть это более четко, мы добавили желтые горизонтальные линии между каждыми двумя соседними кнопками.
  • Кнопки с большим пространством, чем их запрашиваемая высота, не обязательно «заполняют» их. В этом случае фактическое поведение контролируется их выравниванием. Например, они либо выровнены сверху, по центру или кнопке своего пространства, либо полностью заполняют его.
  • Все кнопки охватывают всю ширину макета, так как мы изменяем только VerticalOptions.

Скриншоты

Здесь вы найдете соответствующие скриншоты в высоком разрешении.

Фалько
источник
6
изображение выглядит как [[midfing]], лол. шучу, это было действительно полезно
Джой Рекс,
1
@JoyRex: Ну, возможно, эта версия немного менее запутана. ;)
Фалько
2
Я перепутал с вышеупомянутым выводом. start & startAndExp и оба имеют одинаковый вывод .. В чем разница между ними? Вы можете дать объяснение, если это возможно ..
Ранджит Кумар
1
FillAndExpandэто то, что вы хотите, 99% времени
Стефан Делькруа
1
@RanjithKumar Они одинаковы. Если StackLayout вложен в другого родителя, тогда его FillAndExpand может иметь значение - он будет расширяться в пределах своего родителя.
Миха Маркич
16

В текущей версии Xamarin.Forms есть небольшая ошибка; возможно это было там некоторое время.

CenterAndExpand как правило, не расширяется, и обходить его может сбить с толку.

Например, если у вас есть StackLayoutнабор CenterAndExpand, то вы помещаете метку внутри, которая также установлена ​​на CenterAndExpandвас, вы ожидаете, что метка будет иметь полную ширину StackLayout. Нет. Это не будет расширяться. Вы должны установить StackLayout« FillAndExpand», чтобы заставить вложенный объект Label расширяться до полной ширины StackLayout, а затем указать Label центрировать текст, а не сам объект как объект HorizontalTextAlignment="Center". По моему опыту, вам нужно установить родительский и вложенный дочерние элементы, FillAndExpandесли вы действительно хотите убедиться, что он расширяется, чтобы соответствовать.

        <StackLayout HorizontalOptions="FillAndExpand"
                     Orientation="Vertical"
                     WidthRequest="300">
            <Label BackgroundColor="{StaticResource TileAlerts}"
                   HorizontalOptions="FillAndExpand"
                   Style="{StaticResource LabelStyleReversedLrg}"
                   HorizontalTextAlignment="Center"
                   Text="Alerts" />
Клинт Сен-Лоран
источник
3
«... можно ожидать, что метка будет иметь полную ширину StackLayout». Это предположение неверно. Expandиспользуется только для детей StackLayout. Таким образом, если ваш StackLayout является корневым или нет в другом StackLayout, Expandэто никак не повлияет. Вместо этого любой параметр, кроме Fill, будет действовать как «содержимое переноса» для определения размера, что вы и видите.
Therealjohn
Кроме того, расширение работает только для LayoutOptions, которые имеют ту же ориентацию StackLayout. В этом случае макет «Вертикальный», но рассматриваемые параметры горизонтальные (противоположные).
Therealjohn
Термин «AndExpand» неоднозначен. Это можно интерпретировать как «расширить как можно больше» или «расширить только столько, сколько необходимо». Я думаю , что Microsoft должна изменить условия , чтобы что - то менее запутанной, как «CenterAndExpandToParent» или «CenterAndExpandAsNeeded»
technoman23
1

Фалько дал хорошее объяснение, но я хотел добавить к этому другой визуал и то, как эти теги работают в xaml, что я и предпочитаю использовать большую часть времени. Я сделал простой проект для проверки результатов отображения. Вот Xaml для главной страницы:

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

Как видите, это очень простой StackLayout с меткой внутри. Для каждого изображения ниже я оставил StackLayout одинаковым, я просто изменил горизонтальные и вертикальные параметры для записи и изменил текст, чтобы показать выбранные параметры, чтобы вы могли видеть, как запись перемещается и изменяет размеры.

Start vs StartAndExpand Вот код, используемый для запуска:

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

И код, используемый для StartAndExpand:

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

Как видите, визуально нет никакой разницы, кроме того, что в опции StartAndExpand используется больше текста. Это было проверено на моем физическом устройстве Samsung A30. Они могут отображаться по-разному на разных устройствах, но я думаю, что все изображения здесь вместе показывают, что в Xamarin есть некоторые ошибки. В остальном я просто покажу скриншоты, думаю, они говорят сами за себя.

Конец против EndAndExpand

Центр против Центра и Расширения

Fill vs FillAndExpand

Я также рекомендую взглянуть на документацию Microsoft для некоторых дополнительных деталей. Следует отметить, что «Расширение используется только StackLayout».

technoman23
источник
Хорошая визуализация. Но я не понимаю, почему это должно показывать ошибки в Xamarin. Что может сбить с толку, так это то, что метки могут занимать больше места, чем их белый фон (серые области в моем примере). Таким образом, метка «Vert Center» центрируется внутри занимаемого пространства, а не внутри всей страницы. Видимо, спустя почти шесть лет эта тема все еще так же запутана, как и раньше.
Фалько