ScrollView

Browse sample.Examina la muestra.

.NET Multi-platform App UI (.NET MAUI) ScrollView es una vista capaz de desplazarse por su contenido. De forma predeterminada, ScrollView desplaza su contenido verticalmente. ScrollView solo puede tener un único elemento secundario, aunque puede ser otros diseños.

ScrollView define las siguientes propiedades:

  • Content, de tipo View, representa el contenido que se va a mostrar en ScrollView.
  • ContentSize, de tipo Size, representa el tamaño del contenido. Se trata de una propiedad de solo lectura.
  • HorizontalScrollBarVisibility, de tipo ScrollBarVisibility, representa cuando la barra de desplazamiento horizontal está visible.
  • Orientation, de tipo ScrollOrientation, representa la dirección de desplazamiento de ScrollView. El valor predeterminado de esta propiedad es Vertical.
  • ScrollX, de tipo double, indica la posición de desplazamiento X actual. El valor predeterminado de esta propiedad de solo lectura es 0.
  • ScrollY, de tipo double, indica la posición de desplazamiento Y actual. El valor predeterminado de esta propiedad de solo lectura es 0.
  • VerticalScrollBarVisibility, de tipo ScrollBarVisibility, representa cuándo está visible la barra de desplazamiento vertical.

Estas propiedades están respaldadas por objetos BindableProperty, con la excepción de la propiedad Content, lo que significa que pueden ser destinos de los enlaces de datos, y con estilo.

La propiedad Content es ContentProperty de la clase ScrollView y, por tanto, no es necesario establecerla explícitamente desde XAML.

Advertencia

Los objetos ScrollView no se deben anidar. Además, los objetos ScrollView no deben anidarse con otros controles que proporcionan desplazamiento, como CollectionView, ListView y WebView.

ScrollView como diseño raíz

ScrollView solo puede tener un único elemento secundario, que puede ser otros diseños. Por lo tanto, es habitual que ScrollView sea el diseño raíz de una página. Para desplazar su contenido secundario, ScrollView calcula la diferencia entre el alto de su contenido y su propio alto. Esa diferencia es la cantidad que ScrollView puede desplazar su contenido.

A menudo StackLayout será el elemento secundario de ScrollView. En este escenario, ScrollView hace que StackLayout sea tan alto como la suma de las alturas de sus elementos secundarios. Después, ScrollView puede determinar la cantidad en la que se puede desplazar su contenido. Para obtener más información sobre la clase StackLayout, consulte StackLayout.

Precaución

En un ScrollView vertical, evita establecer la propiedad VerticalOptions en Start, Center o End. Al hacerlo, se indica a ScrollView que debe ser tan alto como debe ser, que podría ser cero. Aunque .NET MAUI protege contra esta eventualidad, es mejor evitar el código que sugiere algo que no quieres que pase.

En el ejemplo XAML siguiente se muestra ScrollView como un diseño raíz en una 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>

En este ejemplo, ScrollView tiene su contenido establecido en StackLayout que usa un diseño enlazable para mostrar los campos Colors definidos por .NET MAUI. De forma predeterminada, ScrollView se desplaza verticalmente, lo que revela más contenido:

Screenshot of a root ScrollView layout.

El código de C# equivalente es el siguiente:

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 obtener más información sobre los diseños enlazables, consulta BindableLayout.

ScrollView como diseño secundario

ScrollView puede ser un diseño secundario en otro diseño primario.

A menudo ScrollView será el elemento secundario de Grid. ScrollView requiere un alto específico para calcular la diferencia entre el alto de su contenido y su propia altura, con la diferencia siendo la cantidad que ScrollView puede desplazar su contenido. Cuando ScrollView es el elemento secundario de Grid, no recibe un alto específico. Grid quiere que ScrollView sea lo más corto posible, que es el alto del contenido ScrollView o cero. Para controlar este escenario, RowDefinition de la fila Grid que contiene ScrollView debe establecerse en *. Esto hará que Grid proporcione a ScrollView todo el espacio adicional no requerido por los demás elementos secundarios y ScrollView tendrá una altura específica.

En el ejemplo XAML siguiente se incluye un elemento ScrollView como elemento secundario en 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>

En este ejemplo, el diseño raíz es un Grid que tiene un elemento Label, ScrollView y Button como sus elementos secundarios. ScrollView tiene StackLayout como contenido, con el objeto StackLayout que contiene varios objetos Label. Esta disposición garantiza que el primer Label esté siempre en pantalla, mientras que el texto mostrado por los demás objetos Label se puede desplazar:

Screenshot of a child ScrollView layout.

El código de C# equivalente es el siguiente:

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

Orientación

ScrollView tiene una propiedad Orientation, que representa la dirección de desplazamiento de ScrollView. Esta propiedad es de tipo ScrollOrientation, que define los siguientes miembros:

  • Vertical indica que ScrollView se desplazará verticalmente. Se trata del valor predeterminado de la propiedad Orientation.
  • Horizontal indica que ScrollView se desplazará horizontalmente.
  • Both indica que ScrollView se desplazará horizontal y verticalmente.
  • Neither indica que ScrollView no se desplazará.

Sugerencia

El desplazamiento se puede deshabilitar estableciendo la propiedad Orientation en Neither.

Detectar desplazamiento

ScrollView define un evento Scrolled que se genera para indicar que se produjo el desplazamiento. El objeto ScrolledEventArgs que acompaña al evento Scrolled tiene propiedades ScrollX y ScrollY, ambas de tipo double.

Importante

Las propiedades ScrolledEventArgs.ScrollX y ScrolledEventArgs.ScrollY pueden tener valores negativos, debido al efecto de rebote que se produce al desplazarse hacia atrás hasta el inicio de un ScrollView.

En el ejemplo de XAML siguiente se muestra ScrollView, que establece un controlador para el evento Scrolled:

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

El código de C# equivalente es el siguiente:

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

En este ejemplo, el controlador de eventos OnScrollViewScrolled se ejecuta cuando se desencadena el evento Scrolled:

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

En este ejemplo, el controlador de eventos OnScrollViewScrolled genera los valores del objeto ScrolledEventArgs que acompaña al evento.

Nota:

El evento Scrolled se genera para los desplazamientos iniciados por el usuario y para los desplazamientos mediante programación.

Desplazarse mediante programación

ScrollView define dos métodos ScrollToAsync, que desplazan ScrollView de manera asíncrona. Una de las sobrecargas se desplaza a una posición especificada en ScrollView, mientras que la otra desplaza un elemento especificado a la vista. Ambas sobrecargas tienen un argumento adicional que se puede usar para indicar si se va a animar el desplazamiento.

Importante

Los métodos ScrollToAsync no darán como resultado el desplazamiento cuando la propiedad ScrollView.Orientation esté establecida en Neither.

Desplazar una posición a la vista

Se puede desplazar una posición dentro de un objeto ScrollView con el método ScrollToAsync que acepta argumentos double,x y y. Dado un objeto vertical ScrollView denominado scrollView, en el ejemplo siguiente se muestra cómo desplazarse a 150 unidades independientes del dispositivo desde la parte superior de ScrollView:

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

El tercer argumento para ScrollToAsync es el argumento animated, que determina si se muestra una animación de desplazamiento al desplazarse mediante programación por ScrollView.

Desplazar un elemento a la vista

Un elemento dentro de ScrollView se puede desplazar a la vista con el método ScrollToAsync que acepta argumentos Element y ScrollToPosition. Dado un elemento vertical ScrollView denominado scrollView y un elemento Label denominado label, en el ejemplo siguiente se muestra cómo desplazar un elemento a la vista:

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

El tercer argumento para ScrollToAsync es el argumento animated, que determina si se muestra una animación de desplazamiento al desplazarse mediante programación por ScrollView.

Al desplazarse por un elemento a la vista, la posición exacta del elemento después de que se haya completado el desplazamiento se puede establecer con el segundo argumento, position, del método ScrollToAsync. Este argumento acepta un miembro de enumeración ScrollToPosition:

  • MakeVisible indica que el elemento debe desplazarse hasta que esté visible en ScrollView.
  • Start indica que el elemento debe desplazarse hasta el inicio de ScrollView.
  • Center indica que el elemento debe desplazarse al centro de ScrollView.
  • End indica que el elemento debe desplazarse al final de ScrollView.

Visibilidad de la barra de desplazamiento

ScrollView define las propiedades HorizontalScrollBarVisibility y VerticalScrollBarVisibility, respaldadas por propiedades enlazables. Estas propiedades obtienen o establecen un valor de enumeración ScrollBarVisibility que representa si la barra de desplazamiento horizontal o vertical está visible. La enumeración ScrollBarVisibility define los miembros siguientes:

  • Default indica el comportamiento predeterminado de la barra de desplazamiento para la plataforma y es el valor predeterminado de las propiedades HorizontalScrollBarVisibility y VerticalScrollBarVisibility.
  • Always indica que las barras de desplazamiento estarán visibles, incluso cuando el contenido se ajusta en la vista.
  • Never indica que las barras de desplazamiento no están visibles, incluso si el contenido no encaja en la vista.