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

MainActivityse deriva de (en lugar ActivitydeFragmentActivity ) 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:

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

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

  3. 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:

Captura de pantalla de la aplicación FlashCardPager con ViewPager vacío

En este punto, está ViewPager vacío porque carece de los fragmentos que se usan para rellenar y ViewPagercarece 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. FlashCardFragmentLa vista mostrará la información contenida con una sola tarjeta flash. Cada instancia de FlashCardFragment se hospedará en .ViewPager FlashCardFragmentLa 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 , FragmentPagerAdapterFragmentPagerAdapter 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 Fragmentpara 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 FlashCardDeckAdapterconstructor de clase base de .

Implementar el constructor del adaptador

Cuando la aplicación crea FlashCardDeckAdapteruna 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:

  1. Busca la cadena del problema matemático en la FlashCardDeck cubierta para la posición especificada.

  2. Busca la cadena de respuesta en la FlashCardDeck cubierta para la posición especificada.

  3. Llama al FlashCardFragment método newInstancefactory , pasando el problema de la tarjeta flash y las cadenas de respuesta.

  4. Crea y devuelve una nueva tarjeta Fragment flash que contiene el texto de preguntas y respuestas para esa posición.

ViewPager Cuando representa en Fragmentposition, 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:

Capturas de pantalla de ejemplo de la aplicación FlashCardPager sin indicadores de paginación

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 PagerTabStripobjeto . 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:

Cierre de PagerTabStrip sin texto

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

Capturas de pantalla de FlashCardPager con el número de problema mostrado encima de cada página

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 , ViewPagerpero 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:

Capturas de pantalla de las notificaciones del sistema de la aplicación FlashCardPager cuando se pulsa el problema matemático

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 Fragmentbásica ViewPagerbasada 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.