Xamarin.Forms StackLayout
Дочерние StackLayout
представления упорядочиваются в одномерном стеке по горизонтали или по вертикали. По умолчанию StackLayout
имеет вертикальную ориентацию. Кроме того, StackLayout
можно использовать в качестве родительского макета, содержащего другие дочерние макеты.
Класс StackLayout
определяет следующие свойства:
Orientation
StackOrientation
Тип , представляет направление, в котором размещаются дочерние представления. Значение по умолчанию этого свойства равноVertical
.Spacing
double
Тип , указывает объем пространства между каждым дочерним представлением. Значение по умолчанию этого свойства — шесть единиц, независимых от устройства.
Эти свойства поддерживаются объектами, что означает, что свойства могут быть целевыми BindableProperty
объектами привязки данных и стилем.
Класс StackLayout
является производным от Layout<T>
класса, который определяет Children
свойство типа IList<T>
. Свойство Children
является ContentProperty
классом Layout<T>
, поэтому не требуется явно задавать из XAML.
Совет
Чтобы получить оптимальную производительность макета, следуйте рекомендациям по оптимизации производительности макета.
Вертикальная ориентация
В следующем 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
свойства представляет расстояние между элементом и его смежными элементами. Дополнительные сведения см. в статье Поля и заполнение.
Горизонтальная ориентация
В следующем 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
свойству double
значение:
<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
зависит от значений дочерних представлений HeightRequest
и свойств, а также значений их HorizontalOptions
и VerticalOptions
WidthRequest
свойств. В вертикальном 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
объекта. Поля , и Fill
поля используются для определения выравнивания Label
объектов в родительском элементеStackLayout
:Start
Center
End
StackLayout
учитывает только параметры выравнивания дочерних представлениях, которые находятся в направлении, противоположном ориентации StackLayout
. Поэтому дочерние представления Label
в StackLayout
с вертикальной ориентацией получают свойства HorizontalOptions
в соответствии с одним из следующих полей выравнивания:
Start
, который позиционируетLabel
в левой частиStackLayout
.Center
— располагаетLabel
в центреStackLayout
.End
, который позиционируетLabel
в правой части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 задаются параметры расширения для каждого Label
из 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
, и EndAndExpand
CenterAndExpand
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
занято, параметр расширения ни на что не влияет.
Дополнительные сведения о выравнивании и расширении см. в статье Параметры макета в Xamarin.Forms.
Вложенные объекты 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 }
}
}
},
// ...
}
};
}
}