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 ViewPager
las 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:
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:
Establece la vista desde el recurso de diseño Main.axml.
Recupera una referencia a
ViewPager
desde el diseño.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:
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 deViewPager
.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 datosTreeCatalog
.
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:
Crea una instancia de un nuevo
ImageView
para mostrar la imagen de árbol en la posición especificada. ElMainActivity
de la aplicación es el contexto que se pasará al constructorImageView
.Establece el recurso
ImageView
en el identificador de recurso de imagenTreeCatalog
en la posición especificada.Convierte el contenedor pasado
View
en una referencia deViewPager
. Tenga en cuenta que debe usarJavaCast<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).Agrega el
ImageView
creado alViewPager
y devuelve elImageView
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:
Convierte el contenedor pasado
View
en una referencia deViewPager
.Convierte el objeto Java pasado (
view
) en unView
de C# (view as View
);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:
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:
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:
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
:
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.