Xamarin.Forms CarouselView 布局

CarouselView 定义以下对布局进行控制的属性:

  • ItemsLayout,类型为 LinearItemsLayout,指定要使用的布局。
  • PeekAreaInsets,类型为 Thickness,指定使相邻项部分可见的程度。

这些属性由 BindableProperty 对象提供支持,这意味着这些属性可以作为数据绑定的目标。

默认情况下,CarouselView 将以水平方向显示其项。 屏幕上将显示单个项,轻扫手势可以向前和向后导航浏览项集合。 但也可垂直显示。 这是因为类型为 LinearItemsLayoutItemsLayout 属性继承自 ItemsLayout 类。 ItemsLayout 类定义以下属性:

这些属性由 BindableProperty 对象提供支持,这意味着这些属性可以作为数据绑定的目标。 有关对齐点的详细信息,请参阅 Xamarin.Forms CollectionView 滚动指南中的对齐点

ItemsLayoutOrientation 枚举定义以下成员:

  • Vertical 指示 CarouselView 在添加项时垂直扩展。
  • Horizontal 指示 CarouselView 在添加项时水平扩展。

LinearItemsLayout 类继承自 ItemsLayout 类,并定义类型为 doubleItemSpacing 属性,该属性表示每个项周围的空白空间。 此属性的默认值为 0,其值必须始终大于或等于 0。 LinearItemsLayout 类还定义静态 VerticalHorizontal 成员。 这些成员可用于分别创建垂直列表或水平列表。 或者,可以创建 LinearItemsLayout 对象,并将 ItemsLayoutOrientation 枚举成员指定为参数。

注意

CarouselView 使用本机布局引擎执行布局。

水平布局

默认情况下,CarouselView 将水平显示其项。 因此,无需设置 ItemsLayout 属性即可使用此布局:

<CarouselView ItemsSource="{Binding Monkeys}">
    <CarouselView.ItemTemplate>
        <DataTemplate>
            <StackLayout>
                <Frame HasShadow="True"
                       BorderColor="DarkGray"
                       CornerRadius="5"
                       Margin="20"
                       HeightRequest="300"
                       HorizontalOptions="Center"
                       VerticalOptions="CenterAndExpand">
                    <StackLayout>
                        <Label Text="{Binding Name}"
                               FontAttributes="Bold"
                               FontSize="Large"
                               HorizontalOptions="Center"
                               VerticalOptions="Center" />
                        <Image Source="{Binding ImageUrl}"
                               Aspect="AspectFill"
                               HeightRequest="150"
                               WidthRequest="150"
                               HorizontalOptions="Center" />
                        <Label Text="{Binding Location}"
                               HorizontalOptions="Center" />
                        <Label Text="{Binding Details}"
                               FontAttributes="Italic"
                               HorizontalOptions="Center"
                               MaxLines="5"
                               LineBreakMode="TailTruncation" />
                    </StackLayout>
                </Frame>
            </StackLayout>
        </DataTemplate>
    </CarouselView.ItemTemplate>
</CarouselView>

或者,也可以通过将 ItemsLayout 属性设置为 LinearItemsLayout 对象,并将 HorizontalItemsLayoutOrientation 枚举成员指定为 Orientation 属性值来完成此布局:

<CarouselView ItemsSource="{Binding Monkeys}">
    <CarouselView.ItemsLayout>
        <LinearItemsLayout Orientation="Horizontal" />
    </CarouselView.ItemsLayout>
    ...
</CarouselView>

等效 C# 代码如下:

CarouselView carouselView = new CarouselView
{
    ...
    ItemsLayout = LinearItemsLayout.Horizontal
};

这会导致布局随着新项的添加在水平方向扩张:

iOS 和 Android 上 CarouselView 水平布局的屏幕截图

垂直布局

CarouselView 可以垂直方式显示其项,方法是将 ItemsLayout 属性设置为 LinearItemsLayout 对象,并将 VerticalItemsLayoutOrientation 枚举成员指定为 Orientation 属性值:

<CarouselView ItemsSource="{Binding Monkeys}">
    <CarouselView.ItemsLayout>
        <LinearItemsLayout Orientation="Vertical" />
    </CarouselView.ItemsLayout>
    <CarouselView.ItemTemplate>
        <DataTemplate>
            <StackLayout>
                <Frame HasShadow="True"
                       BorderColor="DarkGray"
                       CornerRadius="5"
                       Margin="20"
                       HeightRequest="300"
                       HorizontalOptions="Center"
                       VerticalOptions="CenterAndExpand">
                    <StackLayout>
                        <Label Text="{Binding Name}"
                               FontAttributes="Bold"
                               FontSize="Large"
                               HorizontalOptions="Center"
                               VerticalOptions="Center" />
                        <Image Source="{Binding ImageUrl}"
                               Aspect="AspectFill"
                               HeightRequest="150"
                               WidthRequest="150"
                               HorizontalOptions="Center" />
                        <Label Text="{Binding Location}"
                               HorizontalOptions="Center" />
                        <Label Text="{Binding Details}"
                               FontAttributes="Italic"
                               HorizontalOptions="Center"
                               MaxLines="5"
                               LineBreakMode="TailTruncation" />
                    </StackLayout>
                </Frame>
            </StackLayout>
        </DataTemplate>
    </CarouselView.ItemTemplate>
</CarouselView>

等效 C# 代码如下:

CarouselView carouselView = new CarouselView
{
    ...
    ItemsLayout = LinearItemsLayout.Vertical
};

这会导致布局随着新项的添加在垂直方向扩张:

iOS 和 Android 上 CarouselView 垂直布局的屏幕截图

部分可见的相邻项

默认情况下,CarouselView 一次性显示全部项。 但是,可以通过将 PeekAreaInsets 属性设置为指定使相邻项部分可见的程度的 Thickness 值来更改此行为。 这对于向用户指示还有其他项要查看非常有用。 以下 XAML 举例说明了如何设置此属性:

<CarouselView ItemsSource="{Binding Monkeys}"
              PeekAreaInsets="100">
    ...
</CarouselView>

等效 C# 代码如下:

CarouselView carouselView = new CarouselView
{
    ...
    PeekAreaInsets = new Thickness(100)
};

结果是相邻项部分显示在屏幕上:

iOS 和 Android 上具有部分可见相邻项的 CollectionView 的屏幕截图

项间距

默认情况下,CarouselView 中的每个项之间没有空格。 可以通过在 CarouselView 使用的项布局上设置 ItemSpacing 属性来更改此行为。

CarouselView 将其 ItemsLayout 属性设置为 LinearItemsLayout 对象时,可以将 LinearItemsLayout.ItemSpacing 属性设置为表示项之间空格的 double 值:

<CarouselView ItemsSource="{Binding Monkeys}">
    <CarouselView.ItemsLayout>
        <LinearItemsLayout Orientation="Vertical"
                           ItemSpacing="20" />
    </CarouselView.ItemsLayout>
    ...
</CarouselView>

注意

LinearItemsLayout.ItemSpacing 属性设置验证回调集,可确保属性值始终大于或等于 0。

等效 C# 代码如下:

CarouselView carouselView = new CarouselView
{
    ...
    ItemsLayout = new LinearItemsLayout(ItemsLayoutOrientation.Vertical)
    {
        ItemSpacing = 20
    }
};

此代码生成一个垂直布局,各个项之间的间距为 20。

动态调整项大小

更改 DataTemplate 中元素的布局相关属性,可在运行时动态调整 CarouselView 中的项大小。 例如,以下示例代码更改 Image 对象的 HeightRequestWidthRequest 属性,以及其父对象 FrameHeightRequest 属性:

void OnImageTapped(object sender, EventArgs e)
{
    Image image = sender as Image;
    image.HeightRequest = image.WidthRequest = image.HeightRequest.Equals(150) ? 200 : 150;
    Frame frame = ((Frame)image.Parent.Parent);
    frame.HeightRequest = frame.HeightRequest.Equals(300) ? 350 : 300;
}

将执行 OnImageTapped 事件处理程序来响应被点击的 Image 对象,并更改图像(及其父 Frame)的尺寸,以便更轻松地查看:

iOS 和 Android 上具有动态项大小调整的 CarouselView 的屏幕截图

从右到左的布局

CarouselView 可按从右到左的流方向布局其内容,方法是将其 FlowDirection 属性设置为 RightToLeft。 但是,最好在页面或根布局上设置 FlowDirection 属性,以便页面或根布局中的所有元素都响应流方向:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="CarouselViewDemos.Views.HorizontalTemplateLayoutRTLPage"
             Title="Horizontal layout (RTL FlowDirection)"
             FlowDirection="RightToLeft">    
    <CarouselView ItemsSource="{Binding Monkeys}">
        ...
    </CarouselView>
</ContentPage>

具有父元素的元素的默认 FlowDirectionMatchParent。 因此,CarouselViewContentPage 继承 FlowDirection 属性值。

有关流方向的详细信息,请参阅从右到左本地化