Compartilhar via


ViewPager com fragmentos

ViewPager é um gerenciador de layout que permite implementar a navegação gestual. A navegação gestual permite que o usuário deslize para a esquerda e para a direita para percorrer páginas de dados. Este guia explica como implementar uma interface do usuário deslizável com ViewPager, usando Fragmentos como as páginas de dados.

Visão geral

ViewPager é frequentemente usado em conjunto com fragmentos para que seja mais fácil gerenciar o ciclo de vida de cada página no ViewPager. Neste passo a passo, ViewPager é usado para criar um aplicativo chamado FlashCardPager que apresenta uma série de problemas matemáticos em cartões flash. Cada cartão flash é implementado como um fragmento. O usuário desliza para a esquerda e para a direita através dos cartões flash e toca em um problema de matemática para revelar sua resposta. Este aplicativo cria uma Fragment instância para cada cartão flash e implementa um adaptador derivado do FragmentPagerAdapter. Em Viewpager e Views, a maior parte do trabalho foi feita em MainActivity métodos de ciclo de vida. No FlashCardPager, a maior parte do trabalho será feito por um Fragment em um de seus métodos de ciclo de vida.

Este guia não aborda os conceitos básicos de fragmentos – se você ainda não estiver familiarizado com fragmentos no Xamarin.Android, consulte Fragmentos para ajudá-lo a começar a usar fragmentos.

Iniciar um projeto de aplicativo

Crie um novo projeto Android chamado FlashCardPager. Em seguida, inicie o Gerenciador de Pacotes NuGet (para obter mais informações sobre como instalar pacotes NuGet, consulte Demonstra Passo a passo: incluindo um NuGet em seu projeto). Encontre e instale o pacote Xamarin.Android.Support.v4 conforme explicado em Viewpager e Views.

Adicionar uma fonte de dados de exemplo

No FlashCardPager, a fonte de dados é um baralho de cartões flash representados pela FlashCardDeck classe, essa fonte de dados fornece o conteúdo do ViewPager item. FlashCardDeck contém uma coleção pronta de problemas e respostas matemáticas. O FlashCardDeck construtor não requer argumentos:

FlashCardDeck flashCards = new FlashCardDeck();

A coleção de cartões flash em FlashCardDeck é organizada de tal forma que cada cartão flash pode ser acessado por um indexador. Por exemplo, a seguinte linha de código recupera o quarto problema de cartão flash no baralho:

string problem = flashCardDeck[3].Problem;

Esta linha de código recupera a resposta correspondente para o problema anterior:

string answer = flashCardDeck[3].Answer;

Como os detalhes de implementação de FlashCardDeck não são relevantes para a compreensão ViewPager, o código não está listado FlashCardDeck aqui. O código-fonte para FlashCardDeck está disponível em FlashCardDeck.cs. Baixe este arquivo de origem (ou copie e cole o código em um novo arquivo FlashCardDeck.cs ) e adicione-o ao seu projeto.

Criar um layout ViewPager

Abra Resources/layout/Main.axml e substitua seu conteúdo pelo seguinte 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>

Esse XML define um que ocupa a ViewPager tela inteira. Observe que você deve usar o nome totalmente qualificado android.support.v4.view.ViewPager porque ViewPager é empacotado em uma biblioteca de suporte. ViewPager está disponível apenas na Biblioteca de Suporte do Android v4, não está disponível no SDK do Android.

Configurar o ViewPager

Edite MainActivity.cs e adicione as seguintes using instruções:

using Android.Support.V4.View;
using Android.Support.V4.App;

Altere a MainActivity declaração de classe para que ela seja derivada de FragmentActivity:

public class MainActivity : FragmentActivity

MainActivityé derivado de (em vez deFragmentActivityActivity) porque FragmentActivity sabe como gerenciar o suporte de fragmentos. Substitua o método OnCreate pelo seguinte código:

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 faz o seguinte:

  1. Define a exibição do recurso de layout Main.axml .

  2. Recupera uma referência ao ViewPager do layout.

  3. Instancia um novo FlashCardDeck como a fonte de dados.

Quando você compila e executa esse código, você deve ver uma exibição semelhante à seguinte captura de tela:

Captura de tela do aplicativo FlashCardPager com ViewPager vazio

Neste ponto, o ViewPager está vazio porque faltam os fragmentos que são usados preencher o ViewPager, e está faltando um adaptador para criar esses fragmentos a partir dos dados no FlashCardDeck.

Nas seções a seguir, um FlashCardFragment é criado para implementar a funcionalidade de cada cartão flash e um FragmentPagerAdapter é criado para conectar o ViewPager aos fragmentos criados a partir de dados no FlashCardDeck.

Criar o fragmento

Cada cartão flash será gerenciado por um fragmento de interface do usuário chamado FlashCardFragment. FlashCardFragmentA visualização do exibirá as informações contidas em um único cartão flash. Cada instância do será hospedada FlashCardFragment ViewPagerpelo . FlashCardFragmentA exibição do consistirá em um TextView que exibe o texto do problema do cartão flash. Essa exibição implementará um manipulador de eventos que usa um Toast para exibir a resposta quando o usuário toca na pergunta do cartão flash.

Criar o layout FlashCardFragment

Antes FlashCardFragment de ser implementado, seu layout deve ser definido. Esse layout é um layout de contêiner de fragmento para um único fragmento. Adicione um novo layout do Android a Recursos/layout chamado flashcard_layout.axml. Abra Resources/layout/flashcard_layout.axml e substitua seu conteúdo pelo seguinte código:

<?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 layout define um único fragmento de cartão flash; Cada fragmento é composto por um TextView que exibe um problema matemático usando uma fonte grande (100sp). Este texto é centralizado vertical e horizontalmente no cartão flash.

Criar a classe FlashCardFragment inicial

Adicione um novo arquivo chamado FlashCardFragment.cs e substitua seu conteúdo pelo seguinte código:

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 esboça a definição essencial Fragment que será usada para exibir um cartão flash. Observe que FlashCardFragment é derivado da versão da biblioteca de Fragment suporte definida no Android.Support.V4.App.Fragment. O construtor está vazio para que o newInstance método de fábrica é usado para criar um novo FlashCardFragment em vez de um construtor.

O OnCreateView método de ciclo de vida cria e configura o TextView. Ele infla o layout para o fragmento TextView e retorna o inflado TextView para o chamador. LayoutInflater e ViewGroup são passados para OnCreateView que ele possa inflar o layout. O savedInstanceState pacote contém dados que OnCreateView são usados para recriar o TextView de um estado salvo.

A visão do fragmento é explicitamente inflada pela chamada para inflater.Inflate. O container argumento é o pai do modo de exibição, e o false sinalizador instrui o inflador a abster-se de adicionar o modo de exibição inflado ao pai do modo de exibição (ele será adicionado quando ViewPager chamar o método do GetItem adaptador mais adiante neste passo a passo).

Adicionar código de estado a FlashCardFragment

Como uma Atividade, um fragmento tem um Bundle que ele usa para salvar e recuperar seu estado. No FlashCardPager, isso Bundle é usado para salvar o texto de pergunta e resposta para o cartão flash associado. Em FlashCardFragment.cs, adicione as seguintes Bundle chaves à parte superior da FlashCardFragment definição de classe:

private static string FLASH_CARD_QUESTION = "card_question";
private static string FLASH_CARD_ANSWER = "card_answer";

Modifique o newInstance método factory para que ele crie um Bundle objeto e use as chaves acima para armazenar o texto de pergunta e resposta passado no fragmento depois que ele for instanciado:

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 o método OnCreateView de ciclo de vida do fragmento para recuperar essas informações do pacote transmitido e carregar o texto da pergunta no 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;
}

A answer variável não é usada aqui, mas será usada posteriormente quando o código do manipulador de eventos for adicionado a esse arquivo.

Criar o adaptador

ViewPagerusa um objeto de controlador de adaptador que fica entre a ViewPager e a fonte de dados (consulte a ilustração no artigo Adaptador ViewPager). Para acessar esses dados, ViewPager é necessário que você forneça um adaptador personalizado derivado do PagerAdapter. Como este exemplo usa fragmentos, ele usa um FragmentPagerAdapterFragmentPagerAdapter é derivado de PagerAdapter. FragmentPagerAdapter Representa cada página como uma Fragment que é mantida persistentemente no gerenciador de fragmentos enquanto o usuário puder retornar à página. À medida que o usuário passa o dedo pelas páginas do ViewPager, o FragmentPagerAdapter extrai informações da fonte de dados e as usa para criar Fragments para a ViewPager exibição.

Ao implementar um FragmentPagerAdapter, você deve substituir o seguinte:

  • Count – propriedade somente leitura que retorna o número de exibições (páginas) disponíveis.

  • GetItem – Retorna o fragmento a ser exibido para a página especificada.

Adicione um novo arquivo chamado FlashCardDeckAdapter.cs e substitua seu conteúdo pelo seguinte código:

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

Esse código resume a implementação essencial FragmentPagerAdapter . Nas seções a seguir, cada um desses métodos é substituído pelo código de trabalho. O objetivo do construtor é passar o gerenciador de fragmentos para o FlashCardDeckAdapterconstrutor de classe base do .

Implementar o construtor adaptador

Quando o aplicativo instancia o FlashCardDeckAdapter, ele fornece uma referência ao gerenciador de fragmentos e um arquivo FlashCardDeck. Adicione a seguinte variável de membro à parte superior da FlashCardDeckAdapter classe em FlashCardDeckAdapter.cs:

public FlashCardDeck flashCardDeck;

Adicione a seguinte linha de código ao FlashCardDeckAdapter construtor:

this.flashCardDeck = flashCards;

Essa linha de código armazena a FlashCardDeck instância que o FlashCardDeckAdapter será usado.

Implementar contagem

A Count implementação é relativamente simples: ele retorna o número de cartões flash no baralho de cartões flash. Substitua Count pelo seguinte código:

public override int Count
{
    get { return flashCardDeck.NumCards; }
}

A NumCards propriedade de retorna o número de cartões flash (número de fragmentos) no conjunto de FlashCardDeck dados.

Implementar GetItem

O GetItem método retorna o fragmento associado à posição fornecida. Quando GetItem é chamado para uma posição no baralho de cartão flash, ele retorna um FlashCardFragment configurado para exibir o problema do cartão flash nessa posição. Substitua o método GetItem pelo seguinte código:

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 faz o seguinte:

  1. Procura a cadeia de caracteres do problema matemático no FlashCardDeck deck para a posição especificada.

  2. Procura a posição especificada na cadeia de caracteres de resposta no FlashCardDeck deck.

  3. Chama o FlashCardFragment método newInstancede fábrica, passando o problema do cartão flash e as cadeias de resposta.

  4. Cria e retorna um novo cartão Fragment flash que contém o texto de pergunta e resposta para essa posição.

Quando o ViewPager renderiza o Fragment at position, ele exibe a TextBox cadeia de caracteres do problema matemático que reside position no baralho de cartões flash.

Adicionar o adaptador ao ViewPager

Agora que o FlashCardDeckAdapter está implementado, é hora de adicioná-lo ao ViewPager. Em MainActivity.cs, adicione a seguinte linha de código ao final do OnCreate método:

FlashCardDeckAdapter adapter =
    new FlashCardDeckAdapter(SupportFragmentManager, flashCards);
viewPager.Adapter = adapter;

Esse código instancia o FlashCardDeckAdapter, passando o SupportFragmentManager no primeiro argumento. (A SupportFragmentManager propriedade de FragmentActivity é usada para obter uma referência ao – para obter mais informações sobre o FragmentManager FragmentManager, consulte Gerenciando fragmentos.)

A implementação principal agora está concluída – compile e execute o aplicativo. Você deve ver a primeira imagem do baralho de cartões flash aparecer na tela, como mostrado à esquerda na próxima captura de tela. Deslize para a esquerda para ver mais cartões flash e, em seguida, deslize para a direita para voltar pelo deck de cartões flash:

Exemplos de capturas de tela do aplicativo FlashCardPager sem indicadores de pager

Adicionar um indicador de pager

Essa implementação mínima ViewPager exibe cada cartão flash no baralho, mas não fornece nenhuma indicação de onde o usuário está dentro do baralho. O próximo passo é adicionar um PagerTabStriparquivo . O PagerTabStrip informa ao usuário sobre qual número do problema é exibido e fornece contexto de navegação exibindo uma dica dos cartões flash anteriores e seguintes.

Abra Resources/layout/Main.axml e adicione um PagerTabStrip ao layout:

<?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>

Ao criar e executar o aplicativo, você verá o vazio PagerTabStrip exibido na parte superior de cada cartão flash:

Closeup de PagerTabStrip sem texto

Exibir um título

Para adicionar um título a cada guia de página, implemente o GetPageTitleFormatted método no adaptador. ViewPager chamadas GetPageTitleFormatted (se implementadas) para obter a cadeia de caracteres de título que descreve a página na posição especificada. Adicione o seguinte método à FlashCardDeckAdapter classe em FlashCardDeckAdapter.cs:

public override Java.Lang.ICharSequence GetPageTitleFormatted(int position)
{
    return new Java.Lang.String("Problem " + (position + 1));
}

Esse código converte a posição no baralho de cartas flash em um número de problema. A cadeia de caracteres resultante é convertida em um Java String que é retornado para o ViewPager. Quando você executa o aplicativo com esse novo método, cada página exibe o número do problema no PagerTabStrip:

Screenshots de FlashCardPager com o número do problema exibido acima de cada página

Você pode deslizar para frente e para trás para ver o número do problema no baralho de cartões flash que é exibido na parte superior de cada cartão flash.

Manipular a entrada do usuário

FlashCardPager apresenta uma série de cartões flash baseados em fragmentos em um ViewPager, mas ainda não tem uma maneira de revelar a resposta para cada problema. Nesta seção, um manipulador de eventos é adicionado ao FlashCardFragment para exibir a resposta quando o usuário toca no texto do problema do cartão flash.

Abra FlashCardFragment.cs e adicione o seguinte código ao final do método antes que a OnCreateView exibição seja retornada ao chamador:

questionBox.Click += delegate
{
    Toast.MakeText(Activity.ApplicationContext,
            "Answer: " + answer, ToastLength.Short).Show();
};

Esse Click manipulador de eventos exibe a resposta em uma notificação do sistema que aparece quando o usuário toca no TextBox. A answer variável foi inicializada anteriormente quando as informações de estado foram lidas do Bundle que foi passado para OnCreateView. Crie e execute o aplicativo e, em seguida, toque no texto do problema em cada cartão flash para ver a resposta:

Capturas de tela do aplicativo FlashCardPager Notificações do sistema quando o problema de matemática é tocado

O FlashCardPager apresentado neste passo a passo usa um MainActivity derivado de FragmentActivity, mas você também pode derivar MainActivity de AppCompatActivity (que também fornece suporte para gerenciar fragmentos).

Resumo

Este passo a passo forneceu um exemplo passo a passo de como criar um aplicativo baseado em básico ViewPagerusando Fragments. Ele apresentou uma fonte de dados de exemplo contendo perguntas e respostas de cartão flash, um ViewPager layout para exibir os cartões flash e uma FragmentPagerAdapter subclasse que conecta o ViewPager à fonte de dados. Para ajudar o usuário a navegar pelos cartões flash, foram incluídas instruções que explicam como adicionar um para exibir o PagerTabStrip número do problema na parte superior de cada página. Finalmente, o código de manipulação de eventos foi adicionado para exibir a resposta quando o usuário toca em um problema de cartão flash.