Xamarin.Forms ScrollView

Автор:

learn.microsoft.com

ScrollView в Xamarin – это макет, который способен прокручивать свое содержимое. Класс ScrollView является производным от класса Layout и по умолчанию прокручивает содержимое вертикально. У ScrollView может быть только один дочерний элемент, хотя это могут быть и другие макеты.

Предупреждение. Объекты ScrollView не должны быть вложенными. Кроме того, объекты ScrollView не должны быть вложены в другие элементы управления, обеспечивающие прокрутку, такие как CollectionView, ListView и WebView.

ScrollView в Xamarin определяет следующие свойства:

  • Content, типа View, представляет содержимое для отображения в ScrollView.
  • ContentSize, типа Size, представляет размер содержимого. Это свойство доступно только для чтения.
  • HorizontalScrollBarVisibility, типа ScrollBarVisibility, представляет, когда горизонтальная полоса прокрутки видна.
  • Orientation, типа ScrollOrientation, представляет направление прокрутки ScrollView. По умолчанию это свойство имеет значение Vertical.
  • ScrollX, тип double, указывает текущую позицию прокрутки X. Значение по умолчанию этого свойства, доступного только для чтения, равно 0.
  • ScrollY, тип double, указывает текущую позицию прокрутки Y. Значение по умолчанию этого свойства, доступного только для чтения, равно 0.
  • VerticalScrollBarVisibility, тип ScrollBarVisibility, представляет, когда полоса вертикальной прокрутки видна.

Эти свойства поддерживаются объектами BindableProperty, за исключением свойства Content, что означает, что они могут быть объектами привязки данных и стилизации.

Свойство Content является свойством ContentProperty класса ScrollView, поэтому его не нужно явно задавать в XAML.

Совет. Чтобы добиться максимальной производительности макета, следуйте рекомендациям в разделе Оптимизация производительности макета.

ScrollView как корневой макет

У ScrollView может быть только один дочерний элемент, который может быть другим макетом. Поэтому обычно ScrollView является корневым макетом на странице. Для прокрутки дочернего содержимого ScrollView вычисляет разницу между высотой содержимого и своей собственной высотой. Эта разница и есть величина, на которую ScrollView может прокрутить свое содержимое.

Часто дочерним элементом ScrollView является StackLayout. В этом случае ScrollView делает высоту StackLayout равной сумме высот его дочерних элементов. Затем ScrollView может определить величину прокрутки своего содержимого. Для получения дополнительной информации о StackLayout см. раздел Xamarin.Forms StackLayout.

Внимание. В вертикальном 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, который использует привязываемый макет для отображения полей Color, определенных Xamarin.Forms. По умолчанию 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;
   }
}

ScrollView как дочерний макет

ScrollView может быть дочерним макетом для другого родительского макета.

Часто ScrollView является дочерним макетом StackLayout. ScrollView требует определенной высоты для вычисления разницы между высотой его содержимого и собственной, причем разница является величиной, на которую ScrollView может прокручивать свое содержимое. Когда ScrollView является дочерним элементом StackLayout, он не получает определенной высоты. StackLayout хочет, чтобы ScrollView был как можно короче, а это либо высота содержимого ScrollView, либо ноль. Чтобы справиться с этим сценарием, свойство VerticalOptions для ScrollView должно быть установлено в 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." />
               <!-- 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.",
                   },
                   // 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.
  • Горизонтальный указывает, что ScrollView будет прокручиваться горизонтально.
  • Both указывает, что ScrollView будет прокручиваться горизонтально и вертикально.
  • Neither указывает, что ScrollView не будет прокручиваться.

Совет. Прокрутку можно отключить, установив для свойства Orientation значение Neither.

Обнаружение прокрутки

ScrollView определяет событие Scrolled, которое запускается, чтобы указать, что произошла прокрутка. Объект ScrolledEventArgs, сопровождающий событие Scrolled, имеет свойства ScrollX и ScrollY, оба типа double.

Важно! Свойства ScrolledEventArgs.ScrollX и ScrolledEventArgs.ScrollY могут иметь отрицательные значения из-за эффекта отскока, который возникает при прокрутке назад к началу ScrollView.

В следующем примере XAML показан ScrollView, который устанавливает обработчик события Scrolled:

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

Эквивалентным кодом на C# является:

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

В этом примере обработчик события OnScrollViewScrolled выполняется при срабатывании события Scrolled:

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

В этом примере обработчик события OnScrollViewScrolled выводит значения объекта ScrolledEventArgs, сопровождающего событие.

Примечание. Событие Scrolled срабатывает при прокрутке, инициированной пользователем, и при программной прокрутке.

Прокрутка программным способом

ScrollView определяет два метода ScrollToAsync, которые асинхронно прокручивают ScrollView. Одна из перегрузок прокручивает до указанной позиции в ScrollView, а другая прокручивает указанный элемент в поле зрения. Обе перегрузки имеют дополнительный аргумент, который может быть использован для указания того, нужно ли анимировать прокрутку.

Важно! Методы ScrollToAsync не приведут к прокрутке, если свойство ScrollView.Orientation установлено в Neither.

Прокрутка позиции в окне просмотра

Позиция в ScrollView может быть прокручена с помощью метода ScrollToAsync, который принимает двойные аргументы x и y. В следующем примере, заданном объектом ScrollView с именем scrollView, показано, как прокрутить до 150 независимых от устройства единиц от верхней части ScrollView:

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

Третьим аргументом ScrollToAsync является аргумент animated, который определяет, будет ли отображаться анимация прокрутки при программном прокручивании ScrollView.

Прокрутка элемента в представление

Элемент в ScrollView можно прокрутить в поле зрения с помощью метода ScrollToAsync, который принимает аргументы Element и ScrollToPosition. Для вертикального ScrollView с именем scrollView и Label с именем label в следующем примере показано, как прокрутить элемент в вид:

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

Третьим аргументом метода ScrollToAsync является аргумент animated, который определяет, будет ли отображаться анимация прокрутки при программном прокручивании ScrollView.

При прокрутке элемента в поле зрения точное положение элемента после завершения прокрутки можно задать с помощью второго аргумента, position, метода ScrollToAsync. Этот аргумент принимает элемент перечисления ScrollToPosition:

  • MakeVisible указывает, что элемент должен прокручиваться до тех пор, пока он не станет видимым в ScrollView.
  • Start указывает, что элемент должен быть прокручен до начала ScrollView.
  • Center указывает, что элемент должен быть прокручен к центру ScrollView.
  • End указывает, что элемент должен быть прокручен до конца ScrollView.

Видимость полосы прокрутки

ScrollView определяет свойства HorizontalScrollBarVisibility и VerticalScrollBarVisibility, которые поддерживаются связываемыми свойствами. Эти свойства получают или устанавливают значение перечисления ScrollBarVisibility, которое представляет, видна ли горизонтальная или вертикальная полоса прокрутки. Перечисление ScrollBarVisibility определяет следующие элементы:

  • Default указывает на поведение полосы прокрутки по умолчанию для платформы и является значением по умолчанию для свойств HorizontalScrollBarVisibility и VerticalScrollBarVisibility.
  • Всегда указывает, что полосы прокрутки будут видны, даже если содержимое помещается в представлении.
  • Never указывает, что полосы прокрутки не будут видны, даже если содержимое не помещается в представлении.

Материалы по теме