Xamarin.Forms StackLayout

Автор:

Перевод с learn.microsoft.com

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

Класс StackLayout в Xamarin определяет следующие свойства:

  • Orientation, тип StackOrientation, представляет собой направление, в котором позиционируются дочерние представления. По умолчанию это свойство имеет значение Vertical.
  • Spacing, тип double, указывает на величину промежутка между каждым дочерним представлением. По умолчанию значение этого свойства равно шести единицам, не зависящим от устройства.

Эти свойства поддерживаются объектами BindableProperty, что означает, что свойства могут быть объектами привязки данных и стилизации.

Класс StackLayout является производным от класса Layout, который определяет свойство Children типа IList. Свойство Children является ContentProperty класса Layout, и поэтому его не нужно явно задавать из XAML.

StackLayout вертикальная ориентация

В следующем XAML показано, как создать вертикально ориентированный StackLayout, содержащий различные дочерние представления:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
            xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
            x:Class="StackLayoutDemos.Views.VerticalStackLayoutPage"
            Title="Vertical StackLayout demo">
   <StackLayout Margin="20">
       <Label Text="Primary colors" />
       <BoxView Color="Red" />
       <BoxView Color="Yellow" />
       <BoxView Color="Blue" />
       <Label Text="Secondary colors" />
       <BoxView Color="Green" />
       <BoxView Color="Orange" />
       <BoxView Color="Purple" />
   </StackLayout>
</ContentPage>

В этом примере создается вертикальный StackLayout, содержащий объекты Label и BoxView. По умолчанию между дочерними представлениями имеется шесть единиц пространства, не зависящих от устройства:

Эквивалентный код на языке C# имеет вид:

public class VerticalStackLayoutPageCS : ContentPage
{
   public VerticalStackLayoutPageCS()
   {
       Title = "Vertical StackLayout demo";
       Content = new StackLayout
       {
           Margin = new Thickness(20),
           Children =
           {
               new Label { Text = "Primary colors" },
               new BoxView { Color = Color.Red },
               new BoxView { Color = Color.Yellow },
               new BoxView { Color = Color.Blue },
               new Label { Text = "Secondary colors" },
               new BoxView { Color = Color.Green },
               new BoxView { Color = Color.Orange },
               new BoxView { Color = Color.Purple }
           }
       };
   }
}

Примечание. Значение свойства Margin представляет собой расстояние между элементом и соседними с ним элементами.

StackLayout горизонтальная ориентация

В следующем XAML показано, как создать горизонтально ориентированный StackLayout, установив для его свойства Orientation значение Horizontal:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
            xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
            x:Class="StackLayoutDemos.Views.HorizontalStackLayoutPage"
            Title="Horizontal StackLayout demo">
   <StackLayout Margin="20"
                Orientation="Horizontal"
                HorizontalOptions="Center">
       <BoxView Color="Red" />
       <BoxView Color="Yellow" />
       <BoxView Color="Blue" />
       <BoxView Color="Green" />
       <BoxView Color="Orange" />
       <BoxView Color="Purple" />
   </StackLayout>
</ContentPage>

В этом примере создается горизонтальный StackLayout, содержащий объекты BoxView, с шестью независимыми от устройства единицами пространства между дочерними представлениями:

Эквивалентный код на языке C# имеет вид:

public HorizontalStackLayoutPageCS()
{
   Title = "Horizontal StackLayout demo";
   Content = new StackLayout
   {
       Margin = new Thickness(20),
       Orientation = StackOrientation.Horizontal,
       HorizontalOptions = LayoutOptions.Center,
       Children =
       {
           new BoxView { Color = Color.Red },
           new BoxView { Color = Color.Yellow },
           new BoxView { Color = Color.Blue },
           new BoxView { Color = Color.Green },
           new BoxView { Color = Color.Orange },
           new BoxView { Color = Color.Purple }
       }
   };
}

Пространство между дочерними представлениями

Расстояние между дочерними представлениями в StackLayout можно изменить, задав свойству Spacing двойное значение:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
            xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
            x:Class="StackLayoutDemos.Views.StackLayoutSpacingPage"
            Title="StackLayout Spacing demo">
   <StackLayout Margin="20"
                Spacing="0">
       <Label Text="Primary colors" />
       <BoxView Color="Red" />
       <BoxView Color="Yellow" />
       <BoxView Color="Blue" />
       <Label Text="Secondary colors" />
       <BoxView Color="Green" />
       <BoxView Color="Orange" />
       <BoxView Color="Purple" />
   </StackLayout>
</ContentPage>

В этом примере создается вертикальный StackLayout, содержащий объекты Label и BoxView, между которыми нет расстояния:

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

Эквивалентный код на языке C# выглядит следующим образом:

public class StackLayoutSpacingPageCS : ContentPage
{
   public StackLayoutSpacingPageCS()
   {
       Title = "StackLayout Spacing demo";
       Content = new StackLayout
       {
           Margin = new Thickness(20),
           Spacing = 0,
           Children =
           {
               new Label { Text = "Primary colors" },
               new BoxView { Color = Color.Red },
               new BoxView { Color = Color.Yellow },
               new BoxView { Color = Color.Blue },
               new Label { Text = "Secondary colors" },
               new BoxView { Color = Color.Green },
               new BoxView { Color = Color.Orange },
               new BoxView { Color = Color.Purple }
           }
       };
   }
}

Положение и размер дочерних представлений в StackLayout

Размер и положение дочерних представлений в StackLayout зависит от значений свойств HeightRequest и WidthRequest, а также от значений их свойств HorizontalOptions и VerticalOptions. В вертикальном StackLayout дочерние представления расширяются, заполняя доступную ширину, если их размер не задан явным образом. Аналогично, в горизонтальном StackLayout дочерние представления расширяются до доступной высоты, если их размер не задан явно.

Свойства HorizontalOptions и VerticalOptions макета StackLayout и его дочерних представлений могут быть установлены в поля из структуры LayoutOptions, которая содержит два параметра компоновки:

  • Выравнивание определяет положение и размер дочернего представления в родительском макете.
  • Расширение указывает, должно ли дочернее представление использовать дополнительное пространство, если оно доступно.

Совет. Не устанавливайте свойства HorizontalOptions и VerticalOptions для StackLayout, если в этом нет необходимости. Значения по умолчанию LayoutOptions.Fill и LayoutOptions.FillAndExpand позволяют наилучшим образом оптимизировать макет. Изменение этих свойств связано с затратами и потреблением памяти, даже при возврате их к значениям по умолчанию.

Выравнивание элементов

В следующем примере XAML задаются параметры выравнивания для каждого дочернего представления в StackLayout:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
            xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
            x:Class="StackLayoutDemos.Views.AlignmentPage"
            Title="Alignment demo">
   <StackLayout Margin="20">
       <Label Text="Start"
              BackgroundColor="Gray"
              HorizontalOptions="Start" />
       <Label Text="Center"
              BackgroundColor="Gray"
              HorizontalOptions="Center" />
       <Label Text="End"
              BackgroundColor="Gray"
              HorizontalOptions="End" />
       <Label Text="Fill"
              BackgroundColor="Gray"
              HorizontalOptions="Fill" />
   </StackLayout>
</ContentPage>

В данном примере для объектов Label заданы параметры выравнивания, позволяющие управлять их положением внутри StackLayout. Поля Start, Center, End и Fill используются для определения выравнивания объектов Label внутри родительского StackLayout:

В StackLayout соблюдаются только те параметры выравнивания дочерних представлений, которые расположены в направлении, противоположном ориентации StackLayout. Поэтому дочерние представления Label в вертикально ориентированном StackLayout устанавливают свои свойства HorizontalOptions в одно из полей выравнивания:

  • Start, которое позиционирует Label в левой части StackLayout.
  • Center, которое центрирует Label в StackLayout.
  • End, которое позиционирует ярлык в правой части StackLayout.
  • Fill, обеспечивающий заполнение Label по ширине StackLayout.

Эквивалентный код на языке C# выглядит следующим образом:

public class AlignmentPageCS : ContentPage
{
   public AlignmentPageCS()
   {
       Title = "Alignment demo";
       Content = new StackLayout
       {
           Margin = new Thickness(20),
           Children =
           {
               new Label { Text = "Start", BackgroundColor = Color.Gray, HorizontalOptions = LayoutOptions.Start },
               new Label { Text = "Center", BackgroundColor = Color.Gray, HorizontalOptions = LayoutOptions.Center },
               new Label { Text = "End", BackgroundColor = Color.Gray, HorizontalOptions = LayoutOptions.End },
               new Label { Text = "Fill", BackgroundColor = Color.Gray, HorizontalOptions = LayoutOptions.Fill }
           }
       };
   }
}

Параметры расширения

Следующий пример XAML устанавливает параметры расширения для каждой метки в StackLayout:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
            xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
            x:Class="StackLayoutDemos.Views.ExpansionPage"
            Title="Expansion demo">
   <StackLayout Margin="20">
       <BoxView BackgroundColor="Red"
                HeightRequest="1" />
       <Label Text="Start"
              BackgroundColor="Gray"
              VerticalOptions="StartAndExpand" />
       <BoxView BackgroundColor="Red"
                HeightRequest="1" />
       <Label Text="Center"
              BackgroundColor="Gray"
              VerticalOptions="CenterAndExpand" />
       <BoxView BackgroundColor="Red"
                HeightRequest="1" />
       <Label Text="End"
              BackgroundColor="Gray"
              VerticalOptions="EndAndExpand" />
       <BoxView BackgroundColor="Red"
                HeightRequest="1" />
       <Label Text="Fill"
              BackgroundColor="Gray"
              VerticalOptions="FillAndExpand" />
       <BoxView BackgroundColor="Red"
                HeightRequest="1" />
   </StackLayout>
</ContentPage>

В этом примере для объектов Label задаются предпочтения расширения, чтобы управлять их размерами в StackLayout. Поля StartAndExpand, CenterAndExpand, EndAndExpand и FillAndExpand используются для определения предпочтения выравнивания, а также того, будет ли Label занимать больше места, если оно доступно в родительском StackLayout:

StackLayout может расширять дочерние представления только в направлении своей ориентации. Поэтому вертикально ориентированный StackLayout может расширять дочерние представления Label, для которых в свойствах VerticalOptions установлено одно из полей расширения. Это означает, что при вертикальном выравнивании каждый Label занимает одинаковое пространство внутри StackLayout. Однако только конечный Label, для которого свойство VerticalOptions установлено в значение FillAndExpand, имеет другой размер.

Совет. При использовании StackLayout убедитесь, что только для одного дочернего вида установлено свойство LayoutOptions.Expands. Это свойство гарантирует, что указанный дочерний вид будет занимать наибольшее пространство, которое может предоставить ему StackLayout.

Эквивалентный код на языке C# выглядит следующим образом:

public ExpansionPageCS()
{
   Title = "Expansion demo";
   Content = new StackLayout
   {
       Margin = new Thickness(20),
       Children =
       {
           new BoxView { BackgroundColor = Color.Red, HeightRequest = 1 },
           new Label { Text = "StartAndExpand", BackgroundColor = Color.Gray, VerticalOptions = LayoutOptions.StartAndExpand },
           new BoxView { BackgroundColor = Color.Red, HeightRequest = 1 },
           new Label { Text = "CenterAndExpand", BackgroundColor = Color.Gray, VerticalOptions = LayoutOptions.CenterAndExpand },
           new BoxView { BackgroundColor = Color.Red, HeightRequest = 1 },
           new Label { Text = "EndAndExpand", BackgroundColor = Color.Gray, VerticalOptions = LayoutOptions.EndAndExpand },
           new BoxView { BackgroundColor = Color.Red, HeightRequest = 1 },
           new Label { Text = "FillAndExpand", BackgroundColor = Color.Gray, VerticalOptions = LayoutOptions.FillAndExpand },
           new BoxView { BackgroundColor = Color.Red, HeightRequest = 1 }
       }
   };
}

Важно. Когда все пространство в StackLayout использовано, настройки расширения не имеют эффекта.

Вложенные объекты StackLayout

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

В следующем XAML показан пример вложенности объектов StackLayout:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
            xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
            x:Class="StackLayoutDemos.Views.CombinedStackLayoutPage"
            Title="Combined StackLayouts demo">
   <StackLayout Margin="20">
       ...
       <Frame BorderColor="Black"
              Padding="5">
           <StackLayout Orientation="Horizontal"
                        Spacing="15">
               <BoxView Color="Red" />
               <Label Text="Red"
                      FontSize="Large"
                      VerticalOptions="Center" />
           </StackLayout>
       </Frame>
       <Frame BorderColor="Black"
              Padding="5">
           <StackLayout Orientation="Horizontal"
                        Spacing="15">
               <BoxView Color="Yellow" />
               <Label Text="Yellow"
                      FontSize="Large"
                      VerticalOptions="Center" />
           </StackLayout>
       </Frame>
       <Frame BorderColor="Black"
              Padding="5">
           <StackLayout Orientation="Horizontal"
                        Spacing="15">
               <BoxView Color="Blue" />
               <Label Text="Blue"
                      FontSize="Large"
                      VerticalOptions="Center" />
           </StackLayout>
       </Frame>
       ...
   </StackLayout>
</ContentPage>

В данном примере родительский StackLayout содержит вложенные объекты StackLayout внутри объектов Frame. Родительский StackLayout ориентирован вертикально, а дочерние объекты StackLayout - горизонтально:

Важно. Чем глубже вложены объекты StackLayout и другие макеты, тем больше вложенные макеты влияют на производительность.

Эквивалентный код на языке C# выглядит следующим образом:

public class CombinedStackLayoutPageCS : ContentPage
{
   public CombinedStackLayoutPageCS()
   {
       Title = "Combined StackLayouts demo";
       Content = new StackLayout
       {
           Margin = new Thickness(20),
           Children =
           {
               new Label { Text = "Primary colors" },
               new Frame
               {
                   BorderColor = Color.Black,
                   Padding = new Thickness(5),
                   Content = new StackLayout
                   {
                       Orientation = StackOrientation.Horizontal,
                       Spacing = 15,
                       Children =
                       {
                           new BoxView { Color = Color.Red },
                           new Label { Text = "Red", FontSize = Device.GetNamedSize(NamedSize.Large, typeof(Label)), VerticalOptions = LayoutOptions.Center }
                       }
                   }
               },
               new Frame
               {
                   BorderColor = Color.Black,
                   Padding = new Thickness(5),
                   Content = new StackLayout
                   {
                       Orientation = StackOrientation.Horizontal,
                       Spacing = 15,
                       Children =
                       {
                           new BoxView { Color = Color.Yellow },
                           new Label { Text = "Yellow", FontSize = Device.GetNamedSize(NamedSize.Large, typeof(Label)), VerticalOptions = LayoutOptions.Center }
                       }
                   }
               },
               new Frame
               {
                   BorderColor = Color.Black,
                   Padding = new Thickness(5),
                   Content = new StackLayout
                   {
                       Orientation = StackOrientation.Horizontal,
                       Spacing = 15,
                       Children =
                       {
                           new BoxView { Color = Color.Blue },
                           new Label { Text = "Blue", FontSize = Device.GetNamedSize(NamedSize.Large, typeof(Label)), VerticalOptions = LayoutOptions.Center }
                       }
                   }
               },
               // ...
           }
       };
   }
}
Оглавление

Материалы по теме