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

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

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

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

Ответ 1

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

Start, Center, End и Fill определяют представление выравнивания в пределах его пространства.

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

Теория

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

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

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

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

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

    • Суффикс 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.

Screenshots

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

Ответ 2

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

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

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

        <StackLayout HorizontalOptions="FillAndExpand"
                     Orientation="Vertical"
                     WidthRequest="300">
            <Label BackgroundColor="{StaticResource TileAlerts}"
                   HorizontalOptions="FillAndExpand"
                   Style="{StaticResource LabelStyleReversedLrg}"
                   HorizontalTextAlignment="Center"
                   Text="Alerts" />