ViewPager con fragmentos
ViewPager es un administrador de diseño que permite implementar la navegación gestural. La navegación Gestural permite al usuario deslizar el dedo hacia la izquierda y hacia la derecha para recorrer las páginas de datos. En esta guía se explica cómo implementar una interfaz de usuario deslizable con ViewPager, mediante fragmentos como páginas de datos.
Información general
ViewPager
a menudo se usa junto con fragmentos para que sea más fácil administrar el ciclo de vida de cada página de ViewPager
. En este tutorial, ViewPager
se usa para crear una aplicación denominada FlashCardPager que presenta una serie de problemas matemáticos en tarjetas flash. Cada tarjeta flash se implementa como un fragmento. El usuario desliza el dedo hacia la izquierda y hacia la derecha a través de las tarjetas flash y pulsa en un problema matemático para mostrar su respuesta. Esta aplicación crea una Fragment
instancia para cada tarjeta flash e implementa un adaptador derivado de FragmentPagerAdapter
. En Viewpager y Views, la mayor parte del trabajo se realizó en MainActivity
los métodos del ciclo de vida. En FlashCardPager, la mayoría del trabajo se realizará mediante uno Fragment
de sus métodos de ciclo de vida.
En esta guía no se tratan los conceptos básicos de los fragmentos; si aún no está familiarizado con los fragmentos de Xamarin.Android, consulte Fragmentos para ayudarle a empezar a trabajar con fragmentos.
Iniciar un proyecto de aplicación
Cree un nuevo proyecto de Android denominado FlashCardPager. A continuación, inicie el Administrador de paquetes NuGet (para obtener más información sobre cómo instalar paquetes NuGet, vea Tutorial: Inclusión de nuGet en el proyecto). Busque e instale el paquete Xamarin.Android.Support.v4 como se explica en Viewpager y Views.
Agregar un origen de datos de ejemplo
En FlashCardPager, el origen de datos es una baraja de tarjetas flash representadas por la FlashCardDeck
clase ; este origen de datos proporciona el ViewPager
contenido del elemento. FlashCardDeck
contiene una colección preparada de problemas matemáticos y respuestas. El FlashCardDeck
constructor no requiere argumentos:
FlashCardDeck flashCards = new FlashCardDeck();
La colección de tarjetas flash en FlashCardDeck
se organiza de forma que un indexador pueda acceder a cada tarjeta flash. Por ejemplo, la siguiente línea de código recupera el cuarto problema de tarjeta flash en la baraja:
string problem = flashCardDeck[3].Problem;
Esta línea de código recupera la respuesta correspondiente al problema anterior:
string answer = flashCardDeck[3].Answer;
Dado que los detalles de implementación de FlashCardDeck
no son relevantes para comprender ViewPager
, el FlashCardDeck
código no aparece aquí.
El código fuente para FlashCardDeck
está disponible en FlashCardDeck.cs.
Descargue este archivo de código fuente (o copie y pegue el código en un nuevo archivo FlashCardDeck.cs ) y agréguelo al proyecto.
Crear un diseño 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
objeto 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 en la biblioteca de soporte técnico de Android v4; no está disponible en Android SDK.
Configurar ViewPager
Edite MainActivity.cs y agregue las siguientes instrucciones using
:
using Android.Support.V4.View;
using Android.Support.V4.App;
Cambie la declaración de MainActivity
clase para que se derive de FragmentActivity
:
public class MainActivity : FragmentActivity
MainActivity
se deriva de (en lugar Activity
deFragmentActivity
) porque FragmentActivity
sabe cómo administrar la compatibilidad de fragmentos. 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);
FlashCardDeck flashCards = new FlashCardDeck();
}
Este código hace lo siguiente:
Establece la vista del recurso de diseño Main.axml .
Recupera una referencia a
ViewPager
desde el diseño.Crea una instancia de un nuevo
FlashCardDeck
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 punto, está ViewPager
vacío porque carece de los fragmentos que se usan para rellenar y ViewPager
carece de un adaptador para crear estos fragmentos a partir de los datos de FlashCardDeck.
En las secciones siguientes, se crea un FlashCardFragment
para implementar la funcionalidad de cada tarjeta flash y se crea un FragmentPagerAdapter
para conectar a ViewPager
los fragmentos creados a partir de los datos de FlashCardDeck
.
Crear el fragmento
Cada tarjeta flash se administrará mediante un fragmento de interfaz de usuario denominado FlashCardFragment
. FlashCardFragment
La vista mostrará la información contenida con una sola tarjeta flash. Cada instancia de FlashCardFragment
se hospedará en .ViewPager
FlashCardFragment
La vista constará de un TextView
objeto que muestra el texto del problema de la tarjeta flash. Esta vista implementará un controlador de eventos que usa para Toast
mostrar la respuesta cuando el usuario pulse la pregunta de la tarjeta flash.
Crear el diseño de FlashCardFragment
Antes de FlashCardFragment
poder implementarse, se debe definir su diseño. Este diseño es un diseño de contenedor de fragmentos para un único fragmento. Agregue un nuevo diseño de Android a Resources/layout denominado flashcard_layout.axml. Abra Resources/layout/flashcard_layout.axml y reemplace su contenido por el código siguiente:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/flash_card_question"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:textAppearance="@android:style/TextAppearance.Large"
android:textSize="100sp"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="Question goes here" />
</RelativeLayout>
Este diseño define un único fragmento de tarjeta flash; cada fragmento se compone de un TextView
objeto que muestra un problema matemático mediante una fuente grande (100 píxeles). Este texto se centra vertical y horizontalmente en la tarjeta flash.
Creación de la clase Initial FlashCardFragment
Agregue un nuevo archivo denominado FlashCardFragment.cs y reemplace su contenido por el código siguiente:
using System;
using Android.OS;
using Android.Views;
using Android.Widget;
using Android.Support.V4.App;
namespace FlashCardPager
{
public class FlashCardFragment : Android.Support.V4.App.Fragment
{
public FlashCardFragment() { }
public static FlashCardFragment newInstance(String question, String answer)
{
FlashCardFragment fragment = new FlashCardFragment();
return fragment;
}
public override View OnCreateView (
LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View view = inflater.Inflate (Resource.Layout.flashcard_layout, container, false);
TextView questionBox = (TextView)view.FindViewById (Resource.Id.flash_card_question);
return view;
}
}
}
Este código quita el código de la definición esencial Fragment
que se usará para mostrar una tarjeta flash. Tenga en cuenta que FlashCardFragment
se deriva de la versión de la biblioteca de compatibilidad de Fragment
definida en Android.Support.V4.App.Fragment
. El constructor está vacío para que el newInstance
método de fábrica se use para crear un nuevo FlashCardFragment
en lugar de un constructor.
El OnCreateView
método de ciclo de vida crea y configura .TextView
Infla el diseño del TextView
fragmento y devuelve el inflado TextView
al autor de la llamada. LayoutInflater
y ViewGroup
se pasan a para OnCreateView
que pueda inflar el diseño. La savedInstanceState
agrupación contiene datos que OnCreateView
usan para volver a crear a TextView
partir de un estado guardado.
La vista del fragmento se infla explícitamente mediante la llamada a inflater.Inflate
. El container
argumento es el elemento primario de la vista y la false
marca indica al inflador que no agregue la vista inflada al elemento primario de la vista (se agregará cuando ViewPager
se llame al método del GetItem
adaptador más adelante en este tutorial).
Agregar código de estado a FlashCardFragment
Al igual que una actividad, un fragmento tiene un Bundle
objeto que usa para guardar y recuperar su estado. En FlashCardPager, se Bundle
usa para guardar el texto de preguntas y respuestas de la tarjeta flash asociada. En FlashCardFragment.cs, agregue las siguientes Bundle
claves a la parte superior de la definición de clase FlashCardFragment
:
private static string FLASH_CARD_QUESTION = "card_question";
private static string FLASH_CARD_ANSWER = "card_answer";
Modifique el newInstance
método factory para que cree un Bundle
objeto y use las claves anteriores para almacenar el texto de preguntas y respuestas pasados en el fragmento después de crear una instancia:
public static FlashCardFragment newInstance(String question, String answer)
{
FlashCardFragment fragment = new FlashCardFragment();
Bundle args = new Bundle();
args.PutString(FLASH_CARD_QUESTION, question);
args.PutString(FLASH_CARD_ANSWER, answer);
fragment.Arguments = args;
return fragment;
}
Modifique el método OnCreateView
de ciclo de vida del fragmento para recuperar esta información del paquete pasado y cargue el texto de la pregunta en :TextBox
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
string question = Arguments.GetString(FLASH_CARD_QUESTION, "");
string answer = Arguments.GetString(FLASH_CARD_ANSWER, "");
View view = inflater.Inflate(Resource.Layout.flashcard_layout, container, false);
TextView questionBox = (TextView)view.FindViewById(Resource.Id.flash_card_question);
questionBox.Text = question;
return view;
}
La answer
variable no se usa aquí, pero se usará más adelante cuando se agregue código del controlador de eventos a este archivo.
Crear el adaptador
ViewPager
usa un objeto de controlador de adaptador que se encuentra entre y ViewPager
el origen de datos (vea la ilustración del artículo Adaptador de ViewPager).
Para acceder a estos datos, ViewPager
es necesario proporcionar un adaptador personalizado derivado de PagerAdapter
. Dado que en este ejemplo se usan fragmentos, se usa , FragmentPagerAdapter
FragmentPagerAdapter
se deriva de PagerAdapter
.
FragmentPagerAdapter
representa cada página como un Fragment
objeto que se mantiene persistentemente en el administrador de fragmentos mientras el usuario pueda volver a la página. A medida que el usuario desliza el dedo por las páginas de ViewPager
, FragmentPagerAdapter
extrae información del origen de datos y la usa para crear Fragment
para que se ViewPager
muestre.
Al implementar un FragmentPagerAdapter
, debe invalidar lo siguiente:
Count : propiedad de solo lectura que devuelve el número de vistas (páginas) disponibles.
GetItem : devuelve el fragmento que se va a mostrar para la página especificada.
Agregue un nuevo archivo denominado FlashCardDeckAdapter.cs y reemplace su contenido por el código siguiente:
using System;
using Android.Views;
using Android.Widget;
using Android.Support.V4.App;
namespace FlashCardPager
{
class FlashCardDeckAdapter : FragmentPagerAdapter
{
public FlashCardDeckAdapter (Android.Support.V4.App.FragmentManager fm, FlashCardDeck flashCards)
: base(fm)
{
}
public override int Count
{
get { throw new NotImplementedException(); }
}
public override Android.Support.V4.App.Fragment GetItem(int position)
{
throw new NotImplementedException();
}
}
}
Este código quita el código de la implementación esencial FragmentPagerAdapter
. En las secciones siguientes, cada uno de estos métodos se reemplaza por código de trabajo. El propósito del constructor es pasar el administrador de fragmentos al FlashCardDeckAdapter
constructor de clase base de .
Implementar el constructor del adaptador
Cuando la aplicación crea FlashCardDeckAdapter
una instancia de , proporciona una referencia al administrador de fragmentos y una instancia de FlashCardDeck
.
Agregue la siguiente variable miembro a la parte superior de la FlashCardDeckAdapter
clase en FlashCardDeckAdapter.cs:
public FlashCardDeck flashCardDeck;
Agregue la siguiente línea de código al FlashCardDeckAdapter
constructor:
this.flashCardDeck = flashCards;
Esta línea de código almacena la FlashCardDeck
instancia que usará .FlashCardDeckAdapter
Implementar recuento
La Count
implementación es relativamente sencilla: devuelve el número de tarjetas flash en la baraja de tarjetas flash. Reemplaza Count
por el código siguiente:
public override int Count
{
get { return flashCardDeck.NumCards; }
}
La NumCards
propiedad de FlashCardDeck
devuelve el número de tarjetas flash (número de fragmentos) del conjunto de datos.
Implementación de GetItem
El GetItem
método devuelve el fragmento asociado a la posición especificada. Cuando GetItem
se llama a para una posición en la baraja de tarjetas flash, devuelve un FlashCardFragment
configurado para mostrar el problema de la tarjeta flash en esa posición. Reemplace el método GetItem
con el código siguiente:
public override Android.Support.V4.App.Fragment GetItem(int position)
{
return (Android.Support.V4.App.Fragment)
FlashCardFragment.newInstance (
flashCardDeck[position].Problem, flashCardDeck[position].Answer);
}
Este código hace lo siguiente:
Busca la cadena del problema matemático en la
FlashCardDeck
cubierta para la posición especificada.Busca la cadena de respuesta en la
FlashCardDeck
cubierta para la posición especificada.Llama al
FlashCardFragment
métodonewInstance
factory , pasando el problema de la tarjeta flash y las cadenas de respuesta.Crea y devuelve una nueva tarjeta
Fragment
flash que contiene el texto de preguntas y respuestas para esa posición.
ViewPager
Cuando representa en Fragment
position
, muestra la TextBox
cadena que contiene la cadena de problema matemático que reside position
en en la baraja de tarjetas flash.
Agregar el adaptador al ViewPager
Ahora que FlashCardDeckAdapter
se implementa , es el momento de agregarlo a .ViewPager
En MainActivity.cs, agregue la siguiente línea de código al final del OnCreate
método :
FlashCardDeckAdapter adapter =
new FlashCardDeckAdapter(SupportFragmentManager, flashCards);
viewPager.Adapter = adapter;
Este código crea una instancia de FlashCardDeckAdapter
, pasando en SupportFragmentManager
el primer argumento. (La SupportFragmentManager
propiedad de FragmentActivity se usa para obtener una referencia a FragmentManager
, para obtener más información sobre FragmentManager
, vea Managing Fragments).)
La implementación principal ya está completa: compile y ejecute la aplicación. Debería ver que la primera imagen de la baraja flash aparece en la pantalla, como se muestra a la izquierda en la siguiente captura de pantalla. Desliza el dedo hacia la izquierda para ver más tarjetas flash y, a continuación, deslizar hacia la derecha para volver a través de la baraja de tarjetas flash:
Agregar un indicador de paginación
Esta implementación mínima ViewPager
muestra cada tarjeta flash en la baraja, pero no proporciona ninguna indicación sobre dónde está el usuario dentro de la baraja. El siguiente paso consiste en agregar un PagerTabStrip
objeto . PagerTabStrip
informa al usuario sobre qué número de problema se muestra y proporciona contexto de navegación mostrando una sugerencia de las tarjetas flash anteriores y siguientes.
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/pager"
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>
Al compilar y ejecutar la aplicación, debería ver el vacío mostrado PagerTabStrip
en la parte superior de cada tarjeta flash:
Mostrar un título
Para agregar un título a cada pestaña de página, implemente el GetPageTitleFormatted
método en el adaptador. ViewPager
llama GetPageTitleFormatted
a (si se implementa) para obtener la cadena de título que describe la página en la posición especificada. Agregue el método siguiente a la FlashCardDeckAdapter
clase en FlashCardDeckAdapter.cs:
public override Java.Lang.ICharSequence GetPageTitleFormatted(int position)
{
return new Java.Lang.String("Problem " + (position + 1));
}
Este código convierte la posición en la baraja de tarjetas flash a un número de problema. La cadena resultante se convierte en un java String
que se devuelve a ViewPager
. Al ejecutar la aplicación con este nuevo método, cada página muestra el número de problema en :PagerTabStrip
Puede deslizar hacia atrás y hacia adelante para ver el número de problema en la baraja de tarjetas flash que se muestra en la parte superior de cada tarjeta flash.
Controlar la entrada del usuario
FlashCardPager presenta una serie de tarjetas flash basadas en fragmentos en , ViewPager
pero aún no tiene una manera de revelar la respuesta para cada problema. En esta sección, se agrega un controlador de eventos a FlashCardFragment
para mostrar la respuesta cuando el usuario pulsa en el texto del problema de la tarjeta flash.
Abra FlashCardFragment.cs y agregue el código siguiente al final del método justo antes de que se devuelva la vista al autor de OnCreateView
la llamada:
questionBox.Click += delegate
{
Toast.MakeText(Activity.ApplicationContext,
"Answer: " + answer, ToastLength.Short).Show();
};
Este Click
controlador de eventos muestra la respuesta en una notificación del sistema que aparece cuando el usuario pulsa en .TextBox
La answer
variable se inicializó anteriormente cuando se leyó la información de estado de la agrupación que se pasó a OnCreateView
. Compile y ejecute la aplicación y pulse el texto del problema en cada tarjeta flash para ver la respuesta:
FlashCardPager presentado en este tutorial usa un MainActivity
derivado de FragmentActivity
, pero también puede derivar MainActivity
de AppCompatActivity
(que también proporciona compatibilidad para administrar fragmentos). Para ver un AppCompatActivity
ejemplo, vea FlashCardPager en la Galería de ejemplo.
Resumen
En este tutorial se proporciona un ejemplo paso a paso de cómo compilar una aplicación Fragment
básica ViewPager
basada en s. Se presentó un origen de datos de ejemplo que contiene preguntas y respuestas de tarjetas flash, un ViewPager
diseño para mostrar las tarjetas flash y una FragmentPagerAdapter
subclase que conecta con ViewPager
el origen de datos. Para ayudar al usuario a navegar por las tarjetas flash, se incluyeron instrucciones que explican cómo agregar un PagerTabStrip
para mostrar el número de problema en la parte superior de cada página. Por último, se agregó código de control de eventos para mostrar la respuesta cuando el usuario pulsa en un problema de tarjeta flash.