Compartir vía


ViewPager con vistas

ViewPager es un administrador de diseño que permite implementar la navegación por gestos. La navegación por gestos permite al usuario deslizar el dedo hacia la izquierda y hacia la derecha para recorrer páginas de datos. En esta guía se explica cómo implementar una interfaz de usuario deslizable con ViewPager y PagerTabStrip, mediante Vistas como páginas de datos (una guía posterior explica cómo usar fragmentos para las páginas).

Información general

Esta guía es un tutorial que proporciona una demostración paso a paso sobre cómo usar ViewPager para implementar una galería de imágenes de árboles caducas y perennes. En esta aplicación, el usuario desliza el dedo hacia la izquierda y a la derecha a través de un "catálogo de árboles" para ver las imágenes de árbol. En la parte superior de cada página del catálogo, el nombre del árbol aparece en un PagerTabStrip y se muestra una imagen del árbol en un ImageView. Se usa un adaptador para interactuar ViewPager con el modelo de datos subyacente. Esta aplicación implementa un adaptador derivado de PagerAdapter.

Aunque ViewPagerlas aplicaciones basadas en se suelen implementar con Fragment, hay algunos casos de uso relativamente simples en los que no es necesaria la complejidad adicional de Fragment. Por ejemplo, la aplicación básica de la galería de imágenes que se muestra en este tutorial no requiere el uso de Fragment. Dado que el contenido es estático y el usuario solo desliza el dedo hacia atrás y hacia delante entre diferentes imágenes, la implementación se puede mantener más sencilla mediante las vistas y diseños estándar de Android.

Iniciar un proyecto de aplicación

Cree un nuevo proyecto de Android llamado TreePager (consulte Hola, Android para obtener más información sobre cómo crear nuevos proyectos de Android). A continuación, inicie el Administrador de paquetes NuGet. (Para obtener más información sobre cómo instalar paquetes NuGet, consulte Tutorial: Incluir un NuGet en el proyecto). Busque e instale la Biblioteca de soporte técnico de Android v4:

Captura de pantalla de Compatibilidad con NuGet v4 seleccionada en el administrador de paquetes NuGet

Esto también instalará los paquetes adicionales que la Biblioteca de soporte técnico de Android v4.

Agregar un origen de datos de ejemplo

En este ejemplo, el origen de datos del catálogo de árboles (representado por la clase TreeCatalog ) proporciona ViewPager con contenido de elemento. TreeCatalog contiene una colección preparada de imágenes de árbol y títulos de árbol que el adaptador usará para crear View. El constructor TreeCatalog no requiere argumentos:

TreeCatalog treeCatalog = new TreeCatalog();

La colección de imágenes de TreeCatalog se organiza de forma que un indexador pueda tener acceso a cada imagen. Por ejemplo, la siguiente línea de código recupera el identificador de recurso de imagen de la tercera imagen de la colección:

int imageId = treeCatalog[2].imageId;

Dado que los detalles de implementación de TreeCatalog no son relevantes para comprender ViewPager, el código de TreeCatalog no aparece aquí. El código fuente para TreeCatalog está disponible en TreeCatalog.cs. Descargue este archivo de código fuente (o copie y pegue el código en un nuevo archivo TreeCatalog.cs ) y agréguelo al proyecto. Además, descargue y descomprima los archivos de imagen en la carpeta Recurso/Drawable e incluyéndolas en el proyecto.

Crear un diseño de ViewPager

Abra Resources/layout/Main.axml y reemplace su contenido por el siguiente XML:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.view.ViewPager
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/viewpager"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

</android.support.v4.view.ViewPager>

Este XML define un ViewPager que ocupa toda la pantalla. Tenga en cuenta que debe usar el nombre completo android.support.v4.view.ViewPager porque ViewPager está empaquetado en una biblioteca de soporte técnico. ViewPager solo está disponible desde laBiblioteca de soporte técnico de Android v4; no está disponible en Android SDK.

Configurar ViewPager

Edite MainActivity.cs y agregue la siguiente instrucción using:

using Android.Support.V4.View;

Reemplace el método OnCreate con el código siguiente:

protected override void OnCreate(Bundle bundle)
{
    base.OnCreate(bundle);
    SetContentView(Resource.Layout.Main);
    ViewPager viewPager = FindViewById<ViewPager>(Resource.Id.viewpager);
    TreeCatalog treeCatalog = new TreeCatalog();
}

Este código hace lo siguiente:

  1. Establece la vista desde el recurso de diseño Main.axml.

  2. Recupera una referencia a ViewPager desde el diseño.

  3. Crea una instancia de un nuevo TreeCatalog como origen de datos.

Al compilar y ejecutar este código, debería ver una pantalla similar a la siguiente captura de pantalla:

Captura de pantalla de la aplicación que muestra un ViewPager vacío

En este momento, ViewPager está vacío porque carece de un adaptador para acceder al contenido de TreeCatalog. En la sección siguiente, se crea un PagerAdapter para conectar ViewPager a TreeCatalog.

Crear el adaptador

ViewPager usa un objeto de controlador de adaptador que se encuentra entre ViewPager y el origen de datos (vea la ilustración en Adaptador). Para acceder a estos datos, ViewPager requiere que proporcione un adaptador personalizado derivado de PagerAdapter. Este adaptador rellena cada página de ViewPager con contenido del origen de datos. Dado que este origen de datos es específico de la aplicación, el adaptador personalizado es el código que entiende cómo acceder a los datos. A medida que el usuario desliza el dedo por las páginas delViewPager, el adaptador extrae información del origen de datos y la carga en las páginas para que se muestren los ViewPager.

Al implementar un PagerAdapter, debe invalidar lo siguiente:

  • InstantiateItem: Crea la página (View) para una posición determinada y la agrega a la colección de vistas de ViewPager.

  • DestroyItem: quita una página de una posición determinada.

  • Recuento : propiedad de solo lectura que devuelve el número de vistas (páginas) disponibles.

  • IsViewFromObject: determina si una página está asociada a un objeto de clave específico. (El método InstantiateItem crea este objeto). En este ejemplo, el objeto de clave es el objeto de datos TreeCatalog.

Agregue un nuevo archivo denominado TreePagerAdapter.cs y reemplace su contenido por el código siguiente:

using System;
using Android.App;
using Android.Runtime;
using Android.Content;
using Android.Views;
using Android.Widget;
using Android.Support.V4.View;
using Java.Lang;

namespace TreePager
{
    class TreePagerAdapter : PagerAdapter
    {
        public override int Count
        {
            get { throw new NotImplementedException(); }
        }

        public override bool IsViewFromObject(View view, Java.Lang.Object obj)
        {
            throw new NotImplementedException();
        }

        public override Java.Lang.Object InstantiateItem (View container, int position)
        {
            throw new NotImplementedException();
        }

        public override void DestroyItem(View container, int position, Java.Lang.Object view)
        {
            throw new NotImplementedException();
        }
    }
}

Este código quita el código auxiliar de la implementación esencial de PagerAdapter. En las secciones siguientes, cada uno de estos métodos se reemplaza por código de trabajo.

Implemente el constructor

Cuando la aplicación crea una instancia de TreePagerAdapter, proporciona un contexto (MainActivity) y una instancia de TreeCatalog. Agregue las siguientes variables de miembro y constructor a la parte superior de la clase TreePagerAdapter en TreePagerAdapter.cs:

Context context;
TreeCatalog treeCatalog;

public TreePagerAdapter (Context context, TreeCatalog treeCatalog)
{
    this.context = context;
    this.treeCatalog = treeCatalog;
}

El propósito de este constructor es almacenar el contexto y TreeCatalog instancia que usará TreePagerAdapter.

Implementar recuento

La implementación de Count es relativamente sencilla: devuelve el número de árboles del catálogo de árboles. Reemplaza Count por el código siguiente:

public override int Count
{
    get { return treeCatalog.NumTrees; }
}

La propiedad NumTrees de TreeCatalog devuelve el número de árboles (número de páginas) del conjunto de datos.

Implementar InstantiateItem

El método InstantiateItem crea la página para una posición determinada. También debe agregar la vista recién creada a la colección de vistas de ViewPager. Para que esto sea posible, ViewPager se pasa como parámetro de contenedor.

Reemplace el método InstantiateItem con el código siguiente:

public override Java.Lang.Object InstantiateItem (View container, int position)
{
    var imageView = new ImageView (context);
    imageView.SetImageResource (treeCatalog[position].imageId);
    var viewPager = container.JavaCast<ViewPager>();
    viewPager.AddView (imageView);
    return imageView;
}

Este código hace lo siguiente:

  1. Crea una instancia de un nuevo ImageView para mostrar la imagen de árbol en la posición especificada. El MainActivity de la aplicación es el contexto que se pasará al constructor ImageView.

  2. Establece el recurso ImageView en el identificador de recurso de imagen TreeCatalog en la posición especificada.

  3. Convierte el contenedor pasado View en una referencia de ViewPager. Tenga en cuenta que debe usar JavaCast<ViewPager>() para realizar correctamente esta conversión (esto es necesario para que Android realice una conversión de tipo comprobado en tiempo de ejecución).

  4. Agrega el ImageView creado al ViewPager y devuelve el ImageView al autor de la llamada.

Cuando el ViewPager muestra la imagen en position, muestra este ImageView. Inicialmente, se llama a InstantiateItem dos veces para rellenar las dos primeras páginas con vistas. A medida que el usuario se desplaza, se llama de nuevo para mantener las vistas justo detrás y delante del elemento mostrado actualmente.

Implementar DestroyItem

El método DestroyItem quita una página de la posición especificada. En las aplicaciones en las que la vista en cualquier posición determinada puede cambiar, ViewPager debe tener alguna manera de quitar una vista obsoleta en esa posición antes de reemplazarla por una vista nueva. En el ejemplo de TreeCatalog, la vista de cada posición no cambia, por lo que una vista eliminada por DestroyItem simplemente se volverá a agregar cuando se llame a InstantiateItem para esa posición. (Para mejorar la eficacia, podría implementar un grupo para reciclar View que se volverán a mostrar en la misma posición).

Reemplace el método DestroyItem con el código siguiente:

public override void DestroyItem(View container, int position, Java.Lang.Object view)
{
    var viewPager = container.JavaCast<ViewPager>();
    viewPager.RemoveView(view as View);
}

Este código hace lo siguiente:

  1. Convierte el contenedor pasado View en una referencia de ViewPager.

  2. Convierte el objeto Java pasado (view) en un View de C# (view as View);

  3. Quita la vista de ViewPager.

Implementar IsViewFromObject

A medida que el usuario se desliza a la izquierda y a la derecha a través de páginas de contenido, ViewPager llama a IsViewFromObject para comprobar que el View secundario en la posición especificada está asociado al objeto del adaptador para esa misma posición (por lo tanto, el objeto del adaptador se denomina clave de objeto). Para aplicaciones relativamente simples, la asociación es de identidad: la clave de objeto del adaptador en esa instancia es la vista que se devolvió previamente a ViewPager a través de InstantiateItem. Sin embargo, para otras aplicaciones, la clave de objeto puede ser alguna otra instancia de clase específica del adaptador asociada (pero no la misma que) la vista secundaria que ViewPager muestra en esa posición. Solo el adaptador sabe si la vista y la clave de objeto pasadas están asociadas o no.

IsViewFromObject debe implementarse para que PagerAdapter funcione correctamente. Si IsViewFromObject devuelve false para una posición determinada, ViewPager no mostrará la vista en esa posición. En la TreePager aplicación, la clave de objeto devuelta por InstantiateItem es la página View de un árbol, por lo que el código solo tiene que comprobar la identidad (es decir, la clave de objeto y la vista son una y la misma). Reemplaza IsViewFromObject por el código siguiente:

public override bool IsViewFromObject(View view, Java.Lang.Object obj)
{
    return view == obj;
}

Agregar el adaptador a ViewPager

Ahora que se implementa TreePagerAdapter, es el momento de agregarlo a ViewPager. En MainActivity.cs, agregue la siguiente línea de código al final del método OnCreate:

viewPager.Adapter = new TreePagerAdapter(this, treeCatalog);

Este código crea una instancia de TreePagerAdapter, pasando MainActivity como contexto (this). TreeCatalog creado por instancias se pasa al segundo argumento del constructor. La propiedad Adapter de ViewPager se establece en el objeto TreePagerAdapter creado por instancias; esto conecta el TreePagerAdapter al ViewPager.

La implementación principal ya está completa: compile y ejecute la aplicación. Debería ver que la primera imagen del catálogo de árbol aparece en la pantalla, como se muestra a la izquierda en la captura de pantalla siguiente. Deslice el dedo hacia la izquierda para ver más vistas de árbol y, a continuación, deslice el dedo hacia la derecha para volver a través del catálogo de árboles:

Capturas de pantalla de la aplicación TreePager deslizando imágenes de árbol

Agregar un indicador de buscapersonas

Esta implementación mínima ViewPager muestra las imágenes del catálogo de árboles, pero no proporciona ninguna indicación sobre dónde está el usuario dentro del catálogo. El siguiente paso consiste en agregar un PagerTabStrip. PagerTabStrip informa al usuario sobre qué página se muestra y proporciona contexto de navegación mostrando una sugerencia de las páginas anteriores y siguientes. PagerTabStrip está diseñado para utilizarse como indicador para la página actual de un ViewPager; se desplaza y actualiza a medida que el usuario desliza el dedo a través de cada página.

Abra Resources/layout/Main.axml y agregue un PagerTabStrip al diseño:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.view.ViewPager
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/viewpager"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <android.support.v4.view.PagerTabStrip
          android:layout_width="match_parent"
          android:layout_height="wrap_content"
          android:layout_gravity="top"
          android:paddingBottom="10dp"
          android:paddingTop="10dp"
          android:textColor="#fff" />

</android.support.v4.view.ViewPager>

ViewPager y PagerTabStrip están diseñados para trabajar juntos. Al declarar un PagerTabStrip dentro de un diseño de ViewPager, ViewPager buscará automáticamente PagerTabStrip y lo conectará al adaptador. Al compilar y ejecutar la aplicación, debería ver PagerTabStrip vacío que se muestra en la parte superior de cada pantalla:

Captura de pantalla de cierre de un PagerTabStrip vacío

Mostrar un título

Para agregar un título a cada pestaña de página, implemente el método GetPageTitleFormatted en la clase derivada de PagerAdapter. ViewPager llama a GetPageTitleFormatted (si se implementa) para obtener la cadena de título que describe la página en la posición especificada. Agregar el método siguiente a la clase TreePagerAdapter en TreePagerAdapter.cs:

public override Java.Lang.ICharSequence GetPageTitleFormatted(int position)
{
    return new Java.Lang.String(treeCatalog[position].caption);
}

Este código recupera el árbol subtítulo cadena de la página especificada (posición) en el catálogo de árboles, la convierte en Java String y la devuelve a ViewPager. Al ejecutar la aplicación con este nuevo método, cada página muestra el título del árbol en PagerTabStrip. Debería ver el nombre del árbol en la parte superior de la pantalla sin subrayado:

Capturas de pantalla de páginas con pestañas PagerTabStrip rellenadas con texto

Puede deslizar hacia atrás y hacia delante para ver cada imagen de árbol con subtítulos en el catálogo.

Variación de PagerTitleStrip

PagerTitleStrip es muy similar a PagerTabStrip excepto que PagerTabStrip agrega un subrayado para la pestaña seleccionada actualmente. Puede reemplazar PagerTabStrip por PagerTitleStrip en el diseño anterior y volver a ejecutar la aplicación para ver cómo se ve con PagerTitleStrip:

PagerTitleStrip con subrayados quitados del texto

Tenga en cuenta que el subrayado se quita cuando se convierte en PagerTitleStrip.

Resumen

Este tutorial proporciona un ejemplo paso a paso de cómo crear una aplicación básica que se basa en ViewPager sin utilizar Fragment. Se presentó un origen de datos de ejemplo que contiene imágenes y cadenas de título, un diseño de ViewPager para mostrar las imágenes y una subclase PagerAdapter que conecta ViewPager al origen de datos. Para ayudar al usuario a navegar por el conjunto de datos, se incluyeron instrucciones que explican cómo agregar un PagerTabStrip o PagerTitleStrip para mostrar el título de imagen en la parte superior de cada página.