Compartilhar via


ScrollView

Procurar amostra. Procurar no exemplo

O .NET Multi-Platform App UI (.NET MAUI) ScrollView é uma exibição que permite rolar seu conteúdo. Por padrão, o ScrollView rola seu conteúdo verticalmente. Um ScrollView só pode ter um único filho, embora isso possa ser outros layouts.

ScrollView define as propriedades a seguir:

  • O Content, do tipo View, representa o conteúdo a ser exibido no ScrollView.
  • O ContentSize, do tipo Size, representa o tamanho do conteúdo. Trata-se de uma propriedade somente leitura.
  • O HorizontalScrollBarVisibility, do tipo ScrollBarVisibility, representa quando a barra de rolagem horizontal está visível.
  • O Orientation, do tipo ScrollOrientation, representa a direção de rolagem do ScrollView. O valor padrão dessa propriedade é Vertical.
  • O ScrollX, do tipo double, indica a posição de rolagem X atual. O valor padrão dessa propriedade somente leitura é 0.
  • O ScrollY, do tipo double, indica a posição de rolagem Y atual. O valor padrão dessa propriedade somente leitura é 0.
  • O VerticalScrollBarVisibility, do tipo ScrollBarVisibility, representa quando a barra de rolagem vertical está visível.

Essas propriedades são apoiadas por objetos BindableProperty, com exceção da propriedade Content, o que significa que elas podem ser alvos de associações de dados e estilizadas.

A propriedade Content é o ContentProperty da classe ScrollView e, portanto, não precisa ser definida explicitamente no XAML.

Aviso

Os objetos ScrollView não devem ser aninhados. Além disso, os objetos ScrollView não devem ser aninhados com outros controles que fornecem rolagem, como CollectionView, ListView e WebView.

ScrollView como um layout raiz

Um ScrollView só pode ter um único filho, que pode ser outros layouts. Portanto, é comum que um ScrollView seja o layout raiz em uma página. Para rolar seu conteúdo filho, o ScrollView calcula a diferença entre a altura de seu conteúdo e sua própria altura. Essa diferença é a quantidade que o ScrollView pode rolar seu conteúdo.

Muitas vezes, um StackLayout será o filho de um ScrollView. Nesse cenário, o ScrollView faz com que o StackLayout tenha a mesma altura que a soma das alturas de seus filhos. Então o ScrollView consegue determinar a quantidade que seu conteúdo pode ser rolado. Para obter mais informações sobre o StackLayout, confira StackLayout.

Cuidado

Em um ScrollView vertical, evite definir a propriedade VerticalOptions como Start, Center ou End. Fazer isso indica que o ScrollView deve ter apenas a altura necessária, o que pode ser zero. Embora o .NET MAUI proteja contra essa eventualidade, é melhor evitar usar um código que sugira algo que você não queira que aconteça.

O exemplo XAML a seguir tem um ScrollView como layout raiz em uma página:

<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>

Neste exemplo, o ScrollView tem seu conteúdo definido como um StackLayout que usa um layout associável para exibir os campos Colors definidos pelo .NET MAUI. Por padrão, o ScrollView rola verticalmente, o que revela mais conteúdo:

Captura de tela de um layout ScrollView raiz.

Este é o código C# equivalente:

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;
    }
}

Para obter mais informações sobre layouts associáveis, consulte BindableLayout.

ScrollView como um layout filho

Um ScrollView pode ser um layout filho de um layout pai diferente.

Muitas vezes, um ScrollView será o filho de um Grid. Um ScrollView exige uma altura específica para calcular a diferença entre a altura de seu conteúdo e sua própria altura, e a diferença é a quantidade que ScrollView pode rolar seu conteúdo. Quando um ScrollView é filho de um Grid, ele não recebe uma altura específica. O Grid deseja que o ScrollView seja o mais curto possível, que é a altura do conteúdo do ScrollView ou zero. Para lidar com esse cenário, o RowDefinition da linha Grid que contém o ScrollView deve ser definido como *. Isso fará com que o Grid dê ao ScrollView o espaço extra que não foi usado pelos outros filhos e, então, o ScrollView terá uma altura específica.

O exemplo XAML a seguir tem um ScrollView como o layout filho para um Grid:

<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>

Neste exemplo, o layout raiz é um Grid que tem um Label, ScrollView e Button como seus filhos. O ScrollView tem um StackLayout como seu conteúdo, com o StackLayout contendo vários objetos Label. Essa disposição garante que o primeiro Label esteja sempre na tela, enquanto o texto exibido pelos outros objetos Label pode ser rolado:

Captura de tela de um layout ScrollView filho.

Este é o código C# equivalente:

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;
    }
}

Orientação

O ScrollView tem uma propriedade Orientation, que representa a direção de rolagem do ScrollView. Essa propriedade é do tipo ScrollOrientation, que define os seguintes membros:

  • O Vertical indica que o ScrollView irá rolar verticalmente. Esse membro é o valor padrão da propriedade Orientation.
  • O Horizontal indica que o ScrollView irá rolar horizontalmente.
  • O Both indica que o ScrollView irá rolar horizontal e verticalmente.
  • O Neither indica que o ScrollView não irá rolar.

Dica

A rolagem pode ser desabilitada definindo a propriedade Orientation como Neither.

Detectar rolagem

O ScrollView define um evento Scrolled gerado para indicar que a rolagem ocorreu. O objeto ScrolledEventArgs que acompanha o evento Scrolled tem as propriedades ScrollX e ScrollY, ambas do tipo double.

Importante

As propriedades ScrolledEventArgs.ScrollX e ScrolledEventArgs.ScrollY podem ter valores negativos, devido ao efeito de retorno que ocorre ao rolar de volta para o início de ScrollView.

O exemplo XAML a seguir mostra um ScrollView que define um manipulador de eventos para o evento Scrolled:

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

Este é o código C# equivalente:

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

Neste exemplo, o manipulador de eventos OnScrollViewScrolled é executado quando o evento Scrolled é acionado:

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

Neste exemplo, o manipulador de eventos OnScrollViewScrolled gera os valores do objeto ScrolledEventArgs que acompanha o evento.

Observação

O evento Scrolled é gerado para rolagens iniciadas pelo usuário e para rolagens programáticas.

Rolar programaticamente

O ScrollView define dois métodos ScrollToAsync, que rolam de forma assíncrona o ScrollView. Uma das sobrecargas rola para uma posição especificada no ScrollView, enquanto a outra rola um elemento especificado para exibição. Ambas as sobrecargas têm um argumento adicional que pode ser usado para indicar se deseja animar a rolagem.

Importante

Os métodos ScrollToAsync não resultarão em rolagem quando a propriedade ScrollView.Orientation for definida como Neither.

Rolar uma posição para a exibição

Uma posição dentro de um ScrollView pode ser rolada com o método ScrollToAsync, que aceita os argumentos double, x e y. Dado um objeto vertical ScrollView chamado scrollView, o exemplo a seguir mostra como rolar até 150 unidades independentes de dispositivo da parte superior do ScrollView:

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

O terceiro argumento para o ScrollToAsync é o argumento animated, que determina se uma animação de rolagem é exibida ao rolar programaticamente um ScrollView.

Rolar um elemento para a exibição

Um elemento dentro de um ScrollView pode ser rolado para a exibição com o método ScrollToAsync que aceita os argumentos Element e ScrollToPosition. Dado um ScrollView vertical chamado scrollView e um Label chamado label, o exemplo a seguir mostra como rolar um elemento para a exibição:

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

O terceiro argumento para o ScrollToAsync é o argumento animated, que determina se uma animação de rolagem é exibida ao rolar programaticamente um ScrollView.

Ao rolar um elemento para a exibição, a posição exata do elemento após terminar a rolagem pode ser definida com o segundo argumento, position, do método ScrollToAsync. Esse argumento aceita um membro de enumeração ScrollToPosition:

  • MakeVisible indica que o elemento deve ser rolado até ficar visível no ScrollView.
  • Start indica que o elemento deve ser rolado até o início do ScrollView.
  • Center indica que o elemento deve ser rolado até o centro do ScrollView.
  • End indica que o elemento deve ser rolado até o final do ScrollView.

Visibilidade da barra de rolagem

O ScrollView define as propriedades HorizontalScrollBarVisibility e VerticalScrollBarVisibility, que são apoiadas por propriedades associáveis. Essas propriedades obtêm ou definem um valor de enumeração ScrollBarVisibility, que representa se a barra de rolagem horizontal ou vertical está visível. A enumeração ScrollBarVisibility define os seguintes membros:

  • O Default indica o comportamento da barra de rolagem padrão para a plataforma e é o valor padrão das propriedades HorizontalScrollBarVisibility e VerticalScrollBarVisibility.
  • O Always indica que as barras de rolagem estarão visíveis, mesmo quando o conteúdo se ajustar à exibição.
  • O Never indica que as barras de rolagem não estarão visíveis, mesmo que o conteúdo não se ajuste à exibição.