ScrollView

Browse sample. 浏览示例

.NET Multi-platform App UI (.NET MAUI) ScrollView 是能够滚动其内容的视图。 默认情况下,ScrollView 垂直滚动其内容。 ScrollView 只能有一个子项,尽管这可以是其他布局。

ScrollView 定义以下属性:

  • Content,类型为 View,表示要显示在 ScrollView 中的内容。
  • ContentSize,类型为 Size,表示内容的大小。 这是只读属性。
  • HorizontalScrollBarVisibility,类型为 ScrollBarVisibility,表示水平滚动条何时可见。
  • Orientation,类型为 ScrollOrientation,表示 ScrollView 的滚动方向。 此属性的默认值为 Vertical
  • ScrollX,类型为 double,指示当前 X 滚动位置。 此只读属性的默认值为 0。
  • ScrollY,类型为 double,指示当前 Y 滚动位置。 此只读属性的默认值为 0。
  • VerticalScrollBarVisibility,类型为 ScrollBarVisibility,表示垂直滚动条何时可见。

这些属性由 BindableProperty 对象提供支持,但 Content 属性除外;也就是说,它们可以作为数据绑定的目标,并能进行样式设置。

由于 Content 属性是 ScrollView 类的 ContentProperty,因此不需要从 XAML 中显式设置。

警告

不应嵌套 ScrollView 对象。 此外,ScrollView 对象不应与其他提供滚动的控件嵌套,例如 CollectionViewListViewWebView

ScrollView 作为根布局

ScrollView 只能有一个子项,可以是其他布局。 因此,通常 ScrollView 是页面上的根布局。 若要滚动其子内容,ScrollView 计算其内容高度与其自身高度之间的差异。 此差异是 ScrollView 可以滚动其内容的量。

StackLayout 通常是 ScrollView 的子项。 在这种情况下,ScrollView 会使 StackLayout 与其子项的高度之和一样高。 然后,ScrollView 可以确定其内容可以滚动的量。 有关 StackLayout 的详细信息,请参阅 StackLayout

注意

在垂直 ScrollView 中,避免将 VerticalOptions 属性设置为 StartCenterEnd。 这样做会告知 ScrollView 仅需到达需要的高度,这可能为零。 虽然 .NET MAUI 可以防止这种可能发生的情况,但最好避免使用那些可能导致错误的代码。

以下 XAML 示例将 ScrollView 作为页面上的根布局:

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:ScrollViewDemos"
             x:Class="ScrollViewDemos.Views.XAML.ColorListPage"
             Title="ScrollView demo">
    <ScrollView Margin="20">
        <StackLayout BindableLayout.ItemsSource="{x:Static local:NamedColor.All}">
            <BindableLayout.ItemTemplate>
                <DataTemplate>
                    <StackLayout Orientation="Horizontal">
                        <BoxView Color="{Binding Color}"
                                 HeightRequest="32"
                                 WidthRequest="32"
                                 VerticalOptions="Center" />
                        <Label Text="{Binding FriendlyName}"
                               FontSize="24"
                               VerticalOptions="Center" />
                    </StackLayout>
                </DataTemplate>
            </BindableLayout.ItemTemplate>
        </StackLayout>
    </ScrollView>
</ContentPage>

在此示例中,ScrollView 的内容设置为 StackLayout,其使用可绑定布局显示由 .NET MAUI 定义的 Colors 字段。 默认情况下,ScrollView 垂直滚动可显示更多内容:

Screenshot of a root ScrollView layout.

等效 C# 代码如下:

public class ColorListPage : ContentPage
{
    public ColorListPage()
    {
        DataTemplate dataTemplate = new DataTemplate(() =>
        {
            BoxView boxView = new BoxView
            {
                HeightRequest = 32,
                WidthRequest = 32,
                VerticalOptions = LayoutOptions.Center
            };
            boxView.SetBinding(BoxView.ColorProperty, "Color");

            Label label = new Label
            {
                FontSize = 24,
                VerticalOptions = LayoutOptions.Center
            };
            label.SetBinding(Label.TextProperty, "FriendlyName");

            StackLayout horizontalStackLayout = new StackLayout
            {
                Orientation = StackOrientation.Horizontal
            };
            horizontalStackLayout.Add(boxView);
            horizontalStackLayout.Add(label);

            return horizontalStackLayout;
        });

        StackLayout stackLayout = new StackLayout();
        BindableLayout.SetItemsSource(stackLayout, NamedColor.All);
        BindableLayout.SetItemTemplate(stackLayout, dataTemplate);

        ScrollView scrollView = new ScrollView
        {
            Margin = new Thickness(20),
            Content = stackLayout
        };

        Title = "ScrollView demo";
        Content = scrollView;
    }
}

有关可绑定布局的详细信息,请参阅 BindableLayout

ScrollView 作为子布局

ScrollView 可以是不同父布局的子布局。

ScrollView 通常是 Grid 的子项。 ScrollView 需要特定的高度来计算其内容高度与其自身高度之间的差异,该差异是 ScrollView 可以滚动其内容的量。 当 ScrollViewGrid 的子项时,它不会获得特定的高度。 Grid 希望 ScrollView 尽可能短,即 ScrollView 内容的高度或零。 要处理这种情况,包含 ScrollViewGrid 行的 RowDefinition 应设置为 *。 这会使 GridScrollView 提供其他子项不需要的所有额外空间,并且 ScrollView 将具有特定的高度。

下面的 XAML 示例包含作为 Grid 子布局的 ScrollView

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="ScrollViewDemos.Views.XAML.BlackCatPage"
             Title="ScrollView as a child layout demo">
    <Grid Margin="20"
          RowDefinitions="Auto,*,Auto">
        <Label Text="THE BLACK CAT by Edgar Allan Poe"
               FontSize="14"
               FontAttributes="Bold"
               HorizontalOptions="Center" />
        <ScrollView x:Name="scrollView"
                    Grid.Row="1"
                    VerticalOptions="FillAndExpand"
                    Scrolled="OnScrollViewScrolled">
            <StackLayout>
                <Label Text="FOR the most wild, yet most homely narrative which I am about to pen, I neither expect nor solicit belief. Mad indeed would I be to expect it, in a case where my very senses reject their own evidence. Yet, mad am I not -- and very surely do I not dream. But to-morrow I die, and to-day I would unburthen my soul. My immediate purpose is to place before the world, plainly, succinctly, and without comment, a series of mere household events. In their consequences, these events have terrified -- have tortured -- have destroyed me. Yet I will not attempt to expound them. To me, they have presented little but Horror -- to many they will seem less terrible than barroques. Hereafter, perhaps, some intellect may be found which will reduce my phantasm to the common-place -- some intellect more calm, more logical, and far less excitable than my own, which will perceive, in the circumstances I detail with awe, nothing more than an ordinary succession of very natural causes and effects." />
                <!-- More Label objects go here -->
            </StackLayout>
        </ScrollView>
        <Button Grid.Row="2"
                Text="Scroll to end"
                Clicked="OnButtonClicked" />
    </Grid>
</ContentPage>

在此示例中,根布局是 Grid,其子布局有 LabelScrollViewButtonScrollView 包含 StackLayout 作为其内容,还有 StackLayout,其中包含多个 Label 对象。 这种排列可确保第一个 Label 始终在屏幕上显示,而其他 Label 对象显示的文本可以滚动:

Screenshot of a child ScrollView layout.

等效 C# 代码如下:

public class BlackCatPage : ContentPage
{
    public BlackCatPage()
    {
        Label titleLabel = new Label
        {
            Text = "THE BLACK CAT by Edgar Allan Poe",
            // More properties set here to define the Label appearance
        };

        StackLayout stackLayout = new StackLayout();
        stackLayout.Add(new Label { Text = "FOR the most wild, yet most homely narrative which I am about to pen, I neither expect nor solicit belief. Mad indeed would I be to expect it, in a case where my very senses reject their own evidence. Yet, mad am I not -- and very surely do I not dream. But to-morrow I die, and to-day I would unburthen my soul. My immediate purpose is to place before the world, plainly, succinctly, and without comment, a series of mere household events. In their consequences, these events have terrified -- have tortured -- have destroyed me. Yet I will not attempt to expound them. To me, they have presented little but Horror -- to many they will seem less terrible than barroques. Hereafter, perhaps, some intellect may be found which will reduce my phantasm to the common-place -- some intellect more calm, more logical, and far less excitable than my own, which will perceive, in the circumstances I detail with awe, nothing more than an ordinary succession of very natural causes and effects." });
        // More Label objects go here

        ScrollView scrollView = new ScrollView();
        scrollView.Content = stackLayout;
        // ...

        Title = "ScrollView as a child layout demo";
        Grid grid = new Grid
        {
            Margin = new Thickness(20),
            RowDefinitions =
            {
                new RowDefinition { Height = new GridLength(0, GridUnitType.Auto) },
                new RowDefinition { Height = new GridLength(1, GridUnitType.Star) },
                new RowDefinition { Height = new GridLength(0, GridUnitType.Auto) }
            }
        };
        grid.Add(titleLabel);
        grid.Add(scrollView, 0, 1);
        grid.Add(button, 0, 2);

        Content = grid;
    }
}

方向

ScrollView 具有一个 Orientation 属性,该属性表示 ScrollView 的滚动方向 。 此属性的类型为 ScrollOrientation,定义以下成员:

  • Vertical 指示 ScrollView 将垂直滚动。 此成员是 Orientation 属性的默认值。
  • Horizontal 指示 ScrollView 将水平滚动。
  • Both 指示 ScrollView 将水平和垂直滚动。
  • Neither 指示 ScrollView 不会滚动。

提示

通过将 Orientation 属性设置为 Neither,可以禁用滚动。

检测滚动

ScrollView 定义引发以指示滚动发生的 Scrolled 事件。 Scrolled 事件附带的 ScrolledEventArgs 对象包含类型为 doubleScrollXScrollY 属性。

重要

由于回退到 ScrollView 开始时出现的弹跳效果,ScrolledEventArgs.ScrollXScrolledEventArgs.ScrollY 属性可以具有负值。

下面的 XAML 示例显示了为 Scrolled 事件设置事件处理程序的 ScrollView

<ScrollView Scrolled="OnScrollViewScrolled">
    ...
</ScrollView>

等效 C# 代码如下:

ScrollView scrollView = new ScrollView();
scrollView.Scrolled += OnScrollViewScrolled;

在此示例中,当 Scrolled 事件触发时,将执行 OnScrollViewScrolled 事件处理程序:

void OnScrollViewScrolled(object sender, ScrolledEventArgs e)
{
    Console.WriteLine($"ScrollX: {e.ScrollX}, ScrollY: {e.ScrollY}");
}

在此示例中,OnScrollViewScrolled 事件处理程序输出事件附带的 ScrolledEventArgs 对象的值。

注意

Scrolled 事件针对启动滚动和编程滚动的用户引发。

以编程方式滚动

ScrollView 定义两个 ScrollToAsync 异步滚动 ScrollView 的方法。 其中一个重载滚动到 ScrollView 中指定位置,而另一个重载将指定元素滚动到视图中。 这两个重载都有一个附加参数,可用于指示是否对滚动进行动画处理。

重要

ScrollView.Orientation 属性设置为 Neither 时,ScrollToAsync 方法将不会导致滚动。

将位置滚动到视图中

可以使用 ScrollToAsync 方法滚动到 ScrollView 中的位置,该方法接受 doublexy 参数。 假设有一个名为 scrollView 的垂直 ScrollView 对象,以下示例演示如何从 ScrollView 顶部滚动到 150 个独立于设备的单位:

await scrollView.ScrollToAsync(0, 150, true);

ScrollToAsync 的第三个参数是 animated 参数,它决定在以编程方式滚动 ScrollView 时是否显示滚动动画。

将元素滚动到视图中

ScrollView 中的元素可以使用 ScrollToAsync 方法滚动到视图中,该方法接受 ElementScrollToPosition 参数。 假设有一个名为 scrollView 的垂直 ScrollView 和一个名为 labelLabel,下面的示例演示如何将元素滚动到视图:

await scrollView.ScrollToAsync(label, ScrollToPosition.End, true);

ScrollToAsync 的第三个参数是 animated 参数,它决定在以编程方式滚动 ScrollView 时是否显示滚动动画。

当将元素滚动到视图中时,可以使用 ScrollToAsync 方法的第二个参数 position 设置滚动完成后元素的确切位置。 此参数接受 ScrollToPosition 枚举成员:

  • MakeVisible 指示元素应一直滚动,直到该元素在中 ScrollView 可见。
  • Start 指示元素应滚动到 ScrollView 的开头。
  • Center 指示元素应滚动到 ScrollView 的中心。
  • End 指示元素应滚动到 ScrollView 的末尾。

滚动条可见性

ScrollView 定义 HorizontalScrollBarVisibilityVerticalScrollBarVisibility 属性,这些属性由可绑定属性提供支持。 这些属性获取或设置一个 ScrollBarVisibility 枚举值,该值表示水平滚动条还是垂直滚动条可见。 ScrollBarVisibility 枚举定义下列成员:

  • Default 指示平台的默认滚动条行为,并且是 HorizontalScrollBarVisibilityVerticalScrollBarVisibility 属性的默认值。
  • Always 指示滚动条将可见,即使内容适合视图也是如此。
  • Never 指示滚动条将不可见,即使内容不适合视图也是如此。