Xamarin.Forms ScrollView
ScrollView
是一种能够滚动其内容的布局。 ScrollView
类派生自 Layout
类,默认情况下垂直滚动其内容。 ScrollView
只能有一个子项,但也可以是其他布局。
警告
不应嵌套 ScrollView
对象。 此外,ScrollView
对象不应与提供滚动的其他控件(如 CollectionView
、ListView
和 WebView
)嵌套。
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
只能有一个子项,该子项可以是其他布局。 因此,ScrollView
通常是页面上的根布局。 要滚动其子内容,ScrollView
会计算其内容的高度与其自身高度之间的差值。 该差值是 ScrollView
可以滚动其内容的量。
StackLayout
通常是 ScrollView
的子项。 在此应用场景中,ScrollView
导致 StackLayout
与其子项的高度总和一样高。 然后,ScrollView
可以确定其内容可以滚动的量。 有关 StackLayout
的详细信息,请参阅 StackLayoutXamarin.Forms。
注意
在垂直 ScrollView
中,避免将 VerticalOptions
属性设置为 Start
、Center
或 End
。 这样做会告诉 ScrollView
只与它需要的高度一样高,这可能为零。 虽然 Xamarin.Forms 可以避免这种最终性,但最好避免会建议你不想发生的事情的代码。
以下 XAML 示例将 ScrollView
作为页面上的根布局:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:ScrollViewDemos"
x:Class="ScrollViewDemos.Views.ColorListPage"
Title="ScrollView demo">
<ScrollView>
<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
,它使用可绑定布局来显示由 Xamarin.Forms 定义的 Color
字段。 默认情况下,ScrollView
垂直滚动来显示更多内容:
等效 C# 代码如下:
public class ColorListPageCode : ContentPage
{
public ColorListPageCode()
{
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,
Children = { boxView, label }
};
return horizontalStackLayout;
});
StackLayout stackLayout = new StackLayout();
BindableLayout.SetItemsSource(stackLayout, NamedColor.All);
BindableLayout.SetItemTemplate(stackLayout, dataTemplate);
ScrollView scrollView = new ScrollView { Content = stackLayout };
Title = "ScrollView demo";
Content = scrollView;
}
}
有关可绑定布局的详细信息,请参阅 Xamarin.Forms 中的可绑定布局。
ScrollView 作为子布局
ScrollView
可以是不同父布局的子布局。
ScrollView
通常是 StackLayout
的子级。 ScrollView
需要特定的高度来计算其内容高度与其自身高度之间的差值,该差值是 ScrollView
可以滚动其内容的量。 当 ScrollView
是 StackLayout
的子级时,它不会接收特定高度。 StackLayout
希望 ScrollView
尽可能短,它是 ScrollView
内容的高度或零。 若要处理此方案,应将 ScrollView
的 VerticalOptions
属性设置为 FillAndExpand
。 这将导致 StackLayout
为 ScrollView
提供其他子级不需要的所有额外空间,然后 ScrollView
将具有特定高度。
以下 XAML 示例将 ScrollView
作为 StackLayout
的子布局:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ScrollViewDemos.Views.BlackCatPage"
Title="ScrollView as a child layout demo">
<StackLayout Margin="20">
<Label Text="THE BLACK CAT by Edgar Allan Poe"
FontSize="Medium"
FontAttributes="Bold"
HorizontalOptions="Center" />
<ScrollView VerticalOptions="FillAndExpand">
<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>
</StackLayout>
</ContentPage>
在此示例中,有两个 StackLayout
对象。 第一个 StackLayout
是根布局对象,它有一个 Label
对象和一个 ScrollView
作为子级。 ScrollView
的内容为 StackLayout
,而 StackLayout
包含多个 Label
对象。 这样的安排可以确保第一个 Label
始终显示在屏幕上,而其他 Label
对象显示的文本可以滚动:
等效 C# 代码如下:
public class BlackCatPageCS : ContentPage
{
public BlackCatPageCS()
{
Label titleLabel = new Label
{
Text = "THE BLACK CAT by Edgar Allan Poe",
// More properties set here to define the Label appearance
};
ScrollView scrollView = new ScrollView
{
VerticalOptions = LayoutOptions.FillAndExpand,
Content = new StackLayout
{
Children =
{
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
}
}
};
Title = "ScrollView as a child layout demo";
Content = new StackLayout
{
Margin = new Thickness(20),
Children = { titleLabel, scrollView }
};
}
}
方向
ScrollView
具有 Orientation
属性,该属性表示 ScrollView
的滚动方向。 此属性的类型为 ScrollOrientation
,它定义了以下成员:
Vertical
表示ScrollView
将垂直滚动。 此成员是Orientation
属性的默认值。Horizontal
表示ScrollView
将水平滚动。Both
表示ScrollView
将水平和垂直滚动。Neither
表示ScrollView
不会滚动。
提示
通过将 Orientation
属性设置为 Neither
,可以禁用滚动。
检测滚动
ScrollView
定义 Scrolled
事件,它触发时指示发生了滚动。 Scrolled
事件随附的 ScrolledEventArgs
对象包含类型为 double
的 ScrollX
和 ScrollY
属性。
重要说明
ScrolledEventArgs.ScrollX
和 ScrolledEventArgs.ScrollY
属性可以具有负值,因为在滚动回 ScrollView
的起始处时,会产生反弹效果。
下面的 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
方法不会导致滚动。
将位置滚动到视图中
可以使用接受 double
x
和 y
参数的 ScrollToAsync
方法滚动到 ScrollView
中的某个位置。 以下示例显示了在给定一个名为 scrollView
的垂直 ScrollView
对象时,如何从 ScrollView
的顶部滚动到 150 个与设备无关的单元:
await scrollView.ScrollToAsync(0, 150, true);
ScrollToAsync
的第三个参数是 animated
参数,它将确定以编程方式滚动 ScrollView
时是否显示滚动动画。
将元素滚动到视图中
ScrollView
中的元素可以使用接受 Element
和 ScrollToPosition
参数的 ScrollToAsync
方法滚动到视图中。 下面的示例显示了在给定一个名为 scrollView
的垂直 ScrollView
和一个名为 label
的 Label
时,如何将元素滚动到视图中:
await scrollView.ScrollToAsync(label, ScrollToPosition.End, true);
ScrollToAsync
的第三个参数是 animated
参数,它将确定以编程方式滚动 ScrollView
时是否显示滚动动画。
将元素滚动到视图中时,可以使用 ScrollToAsync
方法的第二个参数 position
设置滚动完成后元素的确切位置。 此参数接受一个 ScrollToPosition
枚举成员:
MakeVisible
表示应滚动该元素,直到它在ScrollView
中可见。Start
表示元素应滚动到ScrollView
的起始处。Center
表示应将元素滚动到ScrollView
的中心。End
表示元素应滚动到ScrollView
的末尾。
滚动条可见性
ScrollView
定义由可绑定属性支持的 HorizontalScrollBarVisibility
和 VerticalScrollBarVisibility
属性。 这些属性将获取或设置 ScrollBarVisibility
枚举值,该值表示水平或垂直滚动条是否可见。 ScrollBarVisibility
枚举定义以下成员:
Default
表示平台的默认滚动条行为,是HorizontalScrollBarVisibility
和VerticalScrollBarVisibility
属性的默认值。Always
指示滚动条将可见,即使内容大小适合视图。Never
指示滚动条将不可见,即使内容大小不适合视图。