滚动查看器控件

当要显示的 UI 内容超出某个区域的容纳范围时,请使用滚动查看器控件。

滚动查看器允许内容延伸到视区(可见区域)边界外。 用户可以通过触摸、鼠标滚轮、键盘或游戏板操作滚动查看器图面,或者使用鼠标或笔光标操作滚动查看器滚动条查看此内容。

根据情况,滚动查看器的滚动条使用两种不同的可视化效果,如下图所示:平移指示器(左)和传统滚动条滑块(右)。

显示平移滚动条的屏幕截图,该滚动条是内容右边缘的 2 像素宽垂直线。

显示标准滚动条的屏幕截图、顶部有向上箭头按钮的 6 像素宽垂直线和底部的向下箭头。

重要

WinUI 3 提供两种不同的滚动查看器控件:ScrollViewerScrollView。 每当我们泛泛地谈论滚动查看器控件时,这些信息都适用于这两个控件。

滚动、平移和缩放

使用滚动查看器控件可以对内容进行滚动、平移和缩放

  • 滚动:通过拖动滚动条滑块或使用鼠标滚轮来垂直或水平移动内容。
  • 平移:使用触摸或笔输入垂直或水平移动内容。
    • 有关滚动和平移的详细信息,请参阅平移指南
  • 缩放:在视觉上放大或缩小内容的规模。

滚动条可以感知用户的输入方法,并使用它来确定要显示的可视化效果。

  • 当通过触摸等方式不直接操作滚动条滚动区域时,平移指示器就会出现,显示当前滚动位置。
  • 将鼠标或笔光标移动到平移指示器上方时,它会变为传统滚动条。 拖动滚动条滑块可操作滚动区域。

显示滚动条在光标上移动时,滚动条从窄平移指示器转换为传统拇指的动画。

注意

当滚动条可见时,它以 16px 叠加在 ScrollViewer 中内容的上方。 为确保好的 UX 设计,你会希望保证这一叠加不会遮挡任何交互式内容。 此外,如果你不希望有 UX 重叠,可以在视区边缘为滚动条保留 16px 的填充。

视区和视区范围

滚动查看器由两个主要区域组成,这两个区域对于理解其功能非常重要。 包含所有可滚动内容(隐藏的和可见的)的区域是视区范围。 显示内容的控件可见区域是视区

超出视区或控件可见区域的文本块。

可以使用各种 API 获取这些区域的高度和宽度,以及可滚动高度和宽度(视区范围大小与视区大小之间的差值)。

建议

  • 尽可能针对垂直滚动(而不是水平滚动)进行设计。
  • 对于超出一条视口边界(垂直或水平)的内容区域使用单轴平移。 对于超出两条视口边界(垂直和水平)的内容区域使用双轴平移。
  • 在项视图、列表视图、网格视图、组合框、列表框、文本输入框和中心控件中使用内置滚动功能。 如果项因过多而无法同时显示,用户可以借助这些控件在项列表中水平或垂直滚动。
  • 如果你希望用户可在较大的区域中在两个方向上平移并缩放,请将该图像放置到滚动查看器中。例如,如果你希望用户可以在完整大小的图像(不是调整大小以适应屏幕的图像)中平移和缩放,则可以这样做。
  • 如果用户将滚动查看一段较长的文本,请配置滚动查看器,使其仅在垂直方向滚动。
  • 使用滚动查看器,使之仅包含一个对象。 请注意,该唯一对象可能是布局面板,而布局面板又包含自身的任意数量的对象。
  • 如需在可滚动视图(例如 ScrollViewer 或 ListView)中处理 UIElement 的指针事件,必须调用 UIElement.CancelDirectManipulation 以在该视图中显式禁止支持对元素执行操作事件。 若要在该视图中重新启用操作事件,请调用 UIElement.TryStartDirectManipulation

UWP 和 WinUI 2

注意

ScrollView 控件仅在 WinUI 3 中可用。 对于 UWP 和 WinUI 2,请使用 ScrollViewer 控件。

重要

本文中的信息和示例是针对使用 Windows App SDKWinUI 3 的应用优化的,但通常适用于使用 WinUI 2 的 UWP 应用。 有关特定于平台的信息和示例,请查看 UWP API 参考。

本部分包含在 UWP 或 WinUI 2 应用中使用该控件所需的信息。

此控件的 API 存在于 Windows.UI.Xaml.Controls 命名空间中。

建议使用最新的 WinUI 2 来获取所有控件的最新样式和模板。 WinUI 2.2 或更高版本包含此控件的使用圆角的新模板。 有关详细信息,请参阅圆角半径

创建滚动查看器

WinUI 3 库应用包括大多数 WinUI 3 控件、特性和功能的交互式示例。 通过 Microsoft Store 获取应用,或在 GitHub 上获取源代码

滚动查看器控件可用于通过将内容显式包装在滚动查看器中或通过将滚动查看器放置在内容控件的控件模板中,来使内容可以滚动。

控件模板中的滚动查看器

滚动查看器控件作为其他控件的复合部分的形式存在是普遍情况。 仅当主机控件的布局空间被限制为小于扩展的内容大小时,滚动查看器部件才会显示视区和滚动条。

ItemsView 在其模板中包含一个 ScrollView 控件。 可以通过 ItemsView.ScrollView 属性访问 ScrollView

ListViewGridView 模板始终包含 ScrollViewerTextBoxRichEditBox 也在其模板中包括了 ScrollViewer。 为了影响内置 ScrollViewer 部件的某些行为和属性,ScrollViewer 定义了许多可在样式中设置并在模板绑定中使用的 XAML 附加属性。 有关附加属性的详细信息,请参阅附加属性概述

设置可滚动内容

当滚动查看器内的内容大于滚动查看器的视区内的内容时,该内容会变得可滚动

此示例将 Rectangle 设置为 ScrollView 控件的内容。 用户只能看到该矩形的 500x400 部分,但可以滚动查看其余部分。

<ScrollView Width="500" Height="400">
    <Rectangle Width="1000" Height="800">
        <Rectangle.Fill>
            <LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
                <GradientStop Color="Yellow" Offset="0.0" />
                <GradientStop Color="Red" Offset="0.25" />
                <GradientStop Color="Blue" Offset="0.75" />
                <GradientStop Color="LimeGreen" Offset="1.0" />
            </LinearGradientBrush>
        </Rectangle.Fill>
    </Rectangle>
</ScrollView>

Layout

在上一示例中,矩形的大小被显式设置为大于滚动查看器。 如果允许滚动查看器内容自然增长(就像在列表或文本块中那样),则可将滚动查看器配置为让其内容(视区范围)垂直扩展、水平扩展、同时在这两个方向扩展,或在这两个方向都不扩展。

例如,此文本块将水平增长至其父容器约束它为止,然后将文本换行并垂直增长。

<TextBlock Text="{x:Bind someText}" TextWrapping="WrapWholeWords"/>

当文本块被包装在滚动查看器中时,滚动查看器会限制其水平增长和垂直增长。

垂直表示内容在水平方向上受到限制,但可以在垂直方向上超出视区边界,用户可以上下滚动内容。

一个文本块,该块垂直扩展到视区之外,或控件的可见区域,并显示垂直滚动条。

水平表示内容在垂直方向上受到限制,但可以在水平方向上超出视区边界,用户可以左右滚动内容。

显示水平滚动条超出视区或控件可见区域的文字块。

滚动条可见性

ScrollViewerScrollView 控件使用略有不同的方式来配置内容的水平和垂直滚动。

下表描述了这些属性的可见性选项。

说明
Auto 仅当视区无法显示所有内容时,才会显示滚动条。
禁用(仅 ScrollViewer) 即使视区无法显示所有内容,也不会显示滚动条。 禁止通过用户交互方式进行滚动。 (仍可以编程方式进行滚动。)
Hidden 即使视区无法显示所有内容,也不会显示滚动条。 滚动仍处于启用状态,可以通过触摸、键盘或鼠标滚轮交互方式进行。
Visible 始终显示滚动条。 (在当前的 UX 设计中,只有当鼠标光标位于滚动条上方时才会出现滚动条,除非视区无法显示所有内容。)

(ScrollViewer 使用 ScrollBarVisibility 枚举;ScrollView 使用 ScrollingScrollBarVisibility 枚举。)

方向

ScrollView 控件具有 ContentOrientation 属性,可让你控制内容的布局。 此属性确定内容在没有显式约束的情况下如何增长。 如果对内容显式设置了 HeightWidth,则 ContentOrientation 无效。

下表显示了 ScrollViewContentOrientation 选项以及 ScrollViewer 的等效设置。

方向 ScrollView ScrollViewer
垂直 ContentOrientation="Vertical" VerticalScrollBarVisibility="[Auto][Visible][Hidden]"
HorizontalScrollBarVisibility="Disabled"
水平 ContentOrientation="Horizontal" VerticalScrollBarVisibility="Disabled"
HorizontalScrollBarVisibility="[Auto][Visible][Hidden]"
两者 ContentOrientation="Both" VerticalScrollBarVisibility="[Auto][Visible][Hidden]"
HorizontalScrollBarVisibility="[Auto][Visible][Hidden]"
ContentOrientation="None"
VerticalScrollBarVisibility="Disabled"
HorizontalScrollBarVisibility="Disabled"

垂直布局

默认情况下,滚动查看器的内容布局(方向)是垂直的。

在此示例中,ItemsRepeater 用作 ScrollView 的 Content。 ItemsRepeater 的 UniformGridLayout 将项水平放置在一行中,直到空间(本例中为 500px)用完,然后将下一个项放置在下一行中。 ItemsRepeater 可能高于用户可以看到的 400px,但用户随后可以垂直滚动内容。

默认的 ContentOrientation 值为 Vertical,因此不需要对 ScrollView 进行任何更改。

<ScrollView Width="500" Height="400">
    <ItemsRepeater ItemsSource="{x:Bind Albums}"
                   ItemTemplate="{StaticResource MyTemplate}">
        <ItemsRepeater.Layout>
            <UniformGridLayout RowSpacing="8" ColumnSpacing="8"/>
        </ItemsRepeater.Layout>
    </ItemsRepeater>
</ScrollView>

水平布局

在此示例中,内容是一个将其项进行水平布局的 StackPanel。 滚动查看器配置已更改为支持水平滚动但禁用垂直滚动。

ScrollViewContentOrientation 属性设置为 Horizontal,以允许内容根据需要水平增长。

<ScrollView Width="500" Height="400" ContentOrientation="Horizontal">
    <StackPanel Orientation="Horizontal">
        <Button Width="200" Content="Button 1"/>
        <Button Width="200" Content="Button 2"/>
        <Button Width="200" Content="Button 3"/>
        <Button Width="200" Content="Button 4"/>
        <Button Width="200" Content="Button 5"/>
    </StackPanel>
</ScrollView>

程序化滚动

滚动查看器的 offset 属性为只读属性,但提供了一些方法供你以编程方式进行滚动。

对于 ScrollView 控件,请调用 ScrollTo 方法并传递要滚动到的水平和垂直偏移。 在本例中,仅限垂直滚动,因此使用当前的 HorizontalOffset 值。 若要滚动到顶部,请使用值为 0 的 VerticalOffset。 若要滚动到底部,则将 VerticalOffsetScrollableHeight 设置为相同。

<Button Content="Scroll to top" Click="ScrollTopButton_Click"/>
<Button Content="Scroll to bottom" Click="ScrollBottomButton_Click"/>
<ScrollView x:Name="scrollView" Width="500" Height="400">
    <StackPanel>
        <Button Width="200" Content="Button 1"/>
        <Button Width="200" Content="Button 2"/>
        <Button Width="200" Content="Button 3"/>
        <Button Width="200" Content="Button 4"/>
        <Button Width="200" Content="Button 5"/>
    </StackPanel>
</ScrollView>
private void ScrollTopButton_Click(object sender, RoutedEventArgs e)
{
    scrollView.ScrollTo(
        horizontalOffset: scrollView.HorizontalOffset,
        verticalOffset: 0);
}

private void ScrollBottomButton_Click(object sender, RoutedEventArgs e)
{
    scrollView.ScrollTo(
        horizontalOffset: scrollView.HorizontalOffset,
        verticalOffset: scrollView.ScrollableHeight);
}

ScrollView 还提供了 ScrollBy 方法,可让你从当前偏移开始垂直或水平滚动指定的增量。

Zoom

可以使用滚动查看器让用户在视觉上放大和缩小内容。 视觉缩放交互是通过捏合和张开手势(将手指张开则放大,将手指捏合则缩小)或通过在滚动鼠标滚轮时按 Ctrl 键来执行的。 有关缩放的详细信息,请参阅光学缩放和重设大小

若要通过用户交互启用缩放,请将 ZoomMode 属性设置为 Enabled(默认情况下该属性为 Disabled)。 对 ZoomMode 属性的更改会立即生效,可能会影响正在进行的用户交互。

此示例显示了一个包装在配置为允许缩放的滚动查看器中的图像

<ScrollView Width="500" Height="400"
            ContentOrientation="Both"
            ZoomMode="Enabled">
    <Image Source="Assets/rainier.jpg"/>
</ScrollView>

在这种情况下,图像不受滚动查看器的约束,因此它最初以其原始大小显示。 如果图像源大于视区,则用户需要缩小图像才能看到整个图像,这可能不是预期的行为。

迄今为止放大的一幅山的照片,图片左上角只有蓝天和云层可见。

下一个示例演示如何配置滚动查看器以将图像约束在视区中,使图像在最初加载时会缩小,用户可以根据需要进行放大和滚动操作。

一幅山放大的图片,使前景、山地和天空都可见。

若要将图像约束在 ScrollView 的视区中,请将 ContentOrientation 属性设置为 None。 由于滚动条可见性不受此约束的约束,因此当用户执行放大操作时滚动条会自动出现。

<ScrollView Width="500" Height="400"
            ContentOrientation="None"
            ZoomMode="Enabled">
    <Image Source="Assets/rainier.jpg"/>
</ScrollView>

缩放系数

使用 MinZoomFactorMaxZoomFactor 属性可以控制用户对内容进行缩放的程度。 这些属性对于用户交互和程序化缩放都有效。

  • 默认值:MinZoomFactor="0.1"MaxZoomFactor="10.0"
<ScrollView Width="500" Height="400"
            ContentOrientation="Both"
            ZoomMode="Enabled" 
            MinZoomFactor="1.0" MaxZoomFactor="8.0">
    <Image Source="Assets/rainier.png"/>
</ScrollView>

程序化缩放

ZoomFactor 属性是只读的,但提供了方法供你进行程序化缩放。 其典型用途是将滚动查看器连接到控制缩放程度的滑块或用于重置缩放级别的按钮。 (请参阅 WinUI 3 库应用中的 ScrollViewer 以查看缩放滑块的示例。)

对于 ScrollView 控件,请调用 ZoomTo 方法并将新的缩放系数作为第一个参数传递。

<Slider Header="Zoom" IsEnabled="True"
        Maximum="{x:Bind scrollControl.MaxZoomFactor, Mode=OneWay}"
        Minimum="{x:Bind scrollControl.MinZoomFactor, Mode=OneWay}"
        StepFrequency="0.1"
        ValueChanged="ZoomSlider_ValueChanged" />
<ScrollView Width="500" Height="400"
            ContentOrientation="None"
            ZoomMode="Enabled">
    <Image Source="Assets/rainier.png"/>
</ScrollView>
private void ZoomSlider_ValueChanged(object sender, RangeBaseValueChangedEventArgs e)
{
    if (scrollControl != null)
    {
        scrollControl.ZoomTo(
            zoomFactor: (float)e.NewValue,
            centerPoint: null)
    }
}

ScrollView 还提供了 ZoomBy 方法,可让你根据当前缩放级别按指定的增量进行放大和缩小。

获取示例代码