ViewPager con frammenti
ViewPager è un gestore di layout che consente di implementare lo spostamento gestuale. Lo spostamento gestuale consente all'utente di scorrere rapidamente verso sinistra e destra per scorrere le pagine di dati. Questa guida illustra come implementare un'interfaccia utente con scorrimento rapido con ViewPager, usando Frammenti come pagine di dati.
Panoramica
ViewPager
viene spesso usato in combinazione con frammenti in modo da semplificare la gestione del ciclo di vita di ogni pagina in ViewPager
. In questa procedura dettagliata ViewPager
viene usata per creare un'app denominata FlashCardPager che presenta una serie di problemi matematici sulle schede flash. Ogni scheda flash viene implementata come frammento. L'utente scorre verso sinistra e verso destra attraverso le schede flash e tocca un problema matematico per rivelare la sua risposta. Questa app crea un'istanza Fragment
per ogni scheda flash e implementa un adattatore derivato da FragmentPagerAdapter
. In Viewpager e Views la maggior parte del lavoro è stata eseguita nei MainActivity
metodi del ciclo di vita. In FlashCardPager, la maggior parte del lavoro verrà eseguita da un Fragment
in uno dei metodi del ciclo di vita.
Questa guida non illustra le nozioni di base dei frammenti, se non si ha ancora familiarità con i frammenti in Xamarin.Android, vedere Frammenti per iniziare a usare i frammenti.
Avviare un progetto di app
Creare un nuovo progetto Android denominato FlashCardPager. Avviare quindi il Gestione pacchetti NuGet (per altre informazioni sull'installazione di pacchetti NuGet, vedere Procedura dettagliata: Inclusione di un nuGet nel progetto). Trovare e installare il pacchetto Xamarin.Android.Support.v4 come illustrato in Viewpager e Views.
Aggiungere un'origine dati di esempio
In FlashCardPager, l'origine dati è un mazzo di schede flash rappresentate dalla FlashCardDeck
classe . Questa origine dati fornisce il con contenuto dell'elemento ViewPager
. FlashCardDeck
contiene una raccolta pronta di problemi matematici e risposte. Il FlashCardDeck
costruttore non richiede argomenti:
FlashCardDeck flashCards = new FlashCardDeck();
La raccolta di schede flash in è organizzata in FlashCardDeck
modo che ogni scheda flash sia accessibile da un indicizzatore. Ad esempio, la riga di codice seguente recupera il quarto problema della scheda flash nel mazzo:
string problem = flashCardDeck[3].Problem;
Questa riga di codice recupera la risposta corrispondente al problema precedente:
string answer = flashCardDeck[3].Answer;
Poiché i dettagli di implementazione di FlashCardDeck
non sono rilevanti per comprendere ViewPager
, il FlashCardDeck
codice non è elencato qui.
Il codice sorgente di FlashCardDeck
è disponibile in FlashCardDeck.cs.
Scaricare questo file di origine (o copiare e incollare il codice in un nuovo file di FlashCardDeck.cs ) e aggiungerlo al progetto.
Creare un layout ViewPager
Aprire Resources/layout/Main.axml e sostituirlo con il codice XML seguente:
<?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>
Questo codice XML definisce un oggetto ViewPager
che occupa l'intero schermo. Si noti che è necessario usare il nome completo android.support.v4.view.ViewPager perché ViewPager
è incluso in un pacchetto in una libreria di supporto. ViewPager
è disponibile solo dalla libreria di supporto Android v4. Non è disponibile in Android SDK.
Configurare ViewPager
Modificare MainActivity.cs e aggiungere le istruzioni seguenti using
:
using Android.Support.V4.View;
using Android.Support.V4.App;
Modificare la dichiarazione di MainActivity
classe in modo che venga derivata da FragmentActivity
:
public class MainActivity : FragmentActivity
MainActivity
è derivato daFragmentActivity
(anziché Activity
) perché FragmentActivity
sa come gestire il supporto dei frammenti. Sostituire il metodo OnCreate
con il codice seguente:
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.Main);
ViewPager viewPager = FindViewById<ViewPager>(Resource.Id.viewpager);
FlashCardDeck flashCards = new FlashCardDeck();
}
Il codice effettua quanto segue:
Imposta la vista dalla risorsa di layout Main.axml .
Recupera un riferimento all'oggetto
ViewPager
dal layout.Crea un'istanza di un nuovo
FlashCardDeck
oggetto come origine dati.
Quando si compila ed esegue questo codice, viene visualizzata una visualizzazione simile allo screenshot seguente:
A questo punto, è ViewPager
vuoto perché manca i frammenti usati popolano e ViewPager
manca un adattatore per la creazione di questi frammenti dai dati in FlashCardDeck.
Nelle sezioni seguenti viene creato un oggetto FlashCardFragment
per implementare la funzionalità di ogni scheda flash e viene creato un FragmentPagerAdapter
oggetto per connettere ViewPager
i frammenti creati dai dati in FlashCardDeck
.
Creare il frammento
Ogni scheda flash verrà gestita da un frammento dell'interfaccia utente denominato FlashCardFragment
. FlashCardFragment
La visualizzazione visualizzerà le informazioni contenute con una singola scheda flash. Ogni istanza di FlashCardFragment
sarà ospitata da ViewPager
.
FlashCardFragment
La visualizzazione sarà costituita da un oggetto TextView
che visualizza il testo del problema della scheda flash. Questa visualizzazione implementerà un gestore eventi che usa un Toast
oggetto per visualizzare la risposta quando l'utente tocca la domanda della scheda flash.
Creare il layout FlashCardFragment
Prima di FlashCardFragment
poter essere implementato, è necessario definirne il layout. Questo layout è un layout del contenitore di frammenti per un singolo frammento. Aggiungere un nuovo layout Android a Resources/layout denominato flashcard_layout.axml. Aprire Resources/layout/flashcard_layout.axml e sostituirlo con il codice seguente:
<?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>
Questo layout definisce un singolo frammento di scheda flash; ogni frammento è costituito da un oggetto TextView
che visualizza un problema matematico usando un tipo di carattere grande (100sp). Questo testo è centrato verticalmente e orizzontalmente sulla scheda flash.
Creare la classe FlashCardFragment iniziale
Aggiungere un nuovo file denominato FlashCardFragment.cs e sostituirlo con il codice seguente:
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;
}
}
}
Questo codice stuba la definizione essenziale Fragment
che verrà usata per visualizzare una scheda flash. Si noti che FlashCardFragment
è derivato dalla versione della libreria di supporto di Fragment
definita in Android.Support.V4.App.Fragment
. Il costruttore è vuoto in modo che il newInstance
metodo factory venga usato per creare un nuovo FlashCardFragment
anziché un costruttore.
Il OnCreateView
metodo del ciclo di vita crea e configura .TextView
Gonfia il layout per il frammento e restituisce l'oggetto TextView
gonfiato TextView
al chiamante. LayoutInflater
e ViewGroup
vengono passati a OnCreateView
in modo che possa gonfiare il layout. Il savedInstanceState
bundle contiene dati che OnCreateView
usano per ricreare l'oggetto TextView
da uno stato salvato.
La visualizzazione del frammento viene gonfiata in modo esplicito dalla chiamata a inflater.Inflate
. L'argomento container
è l'elemento padre della visualizzazione e il false
flag indica all'gonfiatore di evitare di aggiungere la visualizzazione gonfiata all'elemento padre della visualizzazione (verrà aggiunto quando ViewPager
il metodo dell'adattatore GetItem
verrà aggiunto più avanti in questa procedura dettagliata).
Aggiungere codice di stato a FlashCardFragment
Analogamente a un'attività, un frammento ha un Bundle
oggetto che usa per salvare e recuperare il relativo stato. In FlashCardPager questo Bundle
viene usato per salvare il testo della domanda e della risposta per la scheda flash associata. In FlashCardFragment.cs aggiungere le chiavi seguenti Bundle
all'inizio della definizione della FlashCardFragment
classe:
private static string FLASH_CARD_QUESTION = "card_question";
private static string FLASH_CARD_ANSWER = "card_answer";
Modificare il newInstance
metodo factory in modo che crei un Bundle
oggetto e usi le chiavi precedenti per archiviare il testo della domanda e della risposta passato nel frammento dopo che è stata creata un'istanza:
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;
}
Modificare il metodo OnCreateView
del ciclo di vita del frammento per recuperare queste informazioni dal bundle passato e caricare il testo della TextBox
domanda in :
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
variabile non viene usata qui, ma verrà usata in un secondo momento quando il codice del gestore eventi viene aggiunto a questo file.
Creare l'adapter
ViewPager
usa un oggetto controller adattatore che si trova tra l'oggetto ViewPager
e l'origine dati (vedere la figura nell'articolo Adapter ViewPager).
Per accedere a questi dati, ViewPager
è necessario fornire un adattatore personalizzato derivato da PagerAdapter
. Poiché in questo esempio vengono usati frammenti, viene usato un FragmentPagerAdapter
oggetto , FragmentPagerAdapter
derivato da PagerAdapter
.
FragmentPagerAdapter
rappresenta ogni pagina come oggetto Fragment
che viene mantenuto in modo permanente nel gestore frammenti, purché l'utente possa tornare alla pagina. Quando l'utente scorre rapidamente le pagine di ViewPager
, FragmentPagerAdapter
estrae le informazioni dall'origine dati e le usa per creare Fragment
per la ViewPager
visualizzazione di .
Quando si implementa un FragmentPagerAdapter
, è necessario eseguire l'override di quanto segue:
Count : proprietà di sola lettura che restituisce il numero di visualizzazioni (pagine) disponibili.
GetItem : restituisce il frammento da visualizzare per la pagina specificata.
Aggiungere un nuovo file denominato FlashCardDeckAdapter.cs e sostituirlo con il codice seguente:
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();
}
}
}
Questo codice stuba l'implementazione essenziale FragmentPagerAdapter
. Nelle sezioni seguenti ognuno di questi metodi viene sostituito con codice funzionante. Lo scopo del costruttore è passare il gestore frammenti al FlashCardDeckAdapter
costruttore della classe di base.
Implementare il costruttore dell'adapter
Quando l'app crea un'istanza di FlashCardDeckAdapter
, fornisce un riferimento al gestore dei frammenti e un'istanza di FlashCardDeck
.
Aggiungere la variabile membro seguente all'inizio della FlashCardDeckAdapter
classe in FlashCardDeckAdapter.cs:
public FlashCardDeck flashCardDeck;
Aggiungere la riga di codice seguente al FlashCardDeckAdapter
costruttore:
this.flashCardDeck = flashCards;
Questa riga di codice archivia l'istanza FlashCardDeck
che FlashCardDeckAdapter
verrà usata da .
Implementa conteggio
L'implementazione Count
è relativamente semplice: restituisce il numero di schede flash nel mazzo di schede flash. Sostituisci Count
con il seguente codice:
public override int Count
{
get { return flashCardDeck.NumCards; }
}
La NumCards
proprietà di FlashCardDeck
restituisce il numero di schede flash (numero di frammenti) nel set di dati.
Implementare GetItem
Il GetItem
metodo restituisce il frammento associato alla posizione specificata. Quando GetItem
viene chiamato per una posizione nel mazzo di schede flash, restituisce un FlashCardFragment
configurato per visualizzare il problema della scheda flash in tale posizione. Sostituire il metodo GetItem
con il codice seguente:
public override Android.Support.V4.App.Fragment GetItem(int position)
{
return (Android.Support.V4.App.Fragment)
FlashCardFragment.newInstance (
flashCardDeck[position].Problem, flashCardDeck[position].Answer);
}
Il codice effettua quanto segue:
Cerca la stringa del problema matematico nel
FlashCardDeck
mazzo per la posizione specificata.Cerca la stringa di risposta nel
FlashCardDeck
mazzo per la posizione specificata.Chiama il
FlashCardFragment
metodonewInstance
factory , passando le stringhe di risposta e il problema della scheda flash.Crea e restituisce una nuova scheda
Fragment
flash contenente il testo della domanda e della risposta per tale posizione.
Quando esegue il rendering di Fragment
ViewPager
in position
, visualizza l'oggetto TextBox
contenente la stringa di problema matematico che si trova position
nel mazzo di schede flash.
Aggiungere l'adapter a ViewPager
Ora che FlashCardDeckAdapter
è implementato, è il momento di aggiungerlo a ViewPager
. In MainActivity.cs aggiungere la riga di codice seguente alla fine del OnCreate
metodo :
FlashCardDeckAdapter adapter =
new FlashCardDeckAdapter(SupportFragmentManager, flashCards);
viewPager.Adapter = adapter;
Questo codice crea un'istanza di FlashCardDeckAdapter
, passando nella SupportFragmentManager
classe nel primo argomento. La SupportFragmentManager
proprietà FragmentActivity viene usata per ottenere un riferimento a FragmentManager
. Per altre informazioni su FragmentManager
, vedere Gestione di frammenti.
L'implementazione principale è ora completa: compilare ed eseguire l'app. Verrà visualizzata la prima immagine del mazzo di carte flash sullo schermo, come illustrato a sinistra nello screenshot successivo. Scorri verso sinistra per visualizzare più schede flash, quindi scorri verso destra per tornare indietro attraverso il mazzo di schede flash:
Aggiungere un indicatore di cercapersone
Questa implementazione minima ViewPager
visualizza ogni scheda flash nel mazzo, ma non fornisce indicazioni sulla posizione dell'utente all'interno del mazzo. Il passaggio successivo consiste nell'aggiungere un oggetto PagerTabStrip
. PagerTabStrip
Informa l'utente su quale numero di problema viene visualizzato e fornisce il contesto di spostamento visualizzando un suggerimento delle schede flash precedenti e successive.
Aprire Resources/layout/Main.axml e aggiungere un oggetto PagerTabStrip
al 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>
Quando si compila ed esegue l'app, viene visualizzato il vuoto PagerTabStrip
visualizzato nella parte superiore di ogni scheda flash:
Visualizzare un titolo
Per aggiungere un titolo a ogni scheda della pagina, implementare il GetPageTitleFormatted
metodo nell'adattatore. ViewPager
chiama GetPageTitleFormatted
(se implementato) per ottenere la stringa del titolo che descrive la pagina nella posizione specificata. Aggiungere il metodo seguente alla FlashCardDeckAdapter
classe in FlashCardDeckAdapter.cs:
public override Java.Lang.ICharSequence GetPageTitleFormatted(int position)
{
return new Java.Lang.String("Problem " + (position + 1));
}
Questo codice converte la posizione nel mazzo di carte flash in un numero di problema. La stringa risultante viene convertita in java String
restituita a ViewPager
. Quando si esegue l'app con questo nuovo metodo, ogni pagina visualizza il numero di problema in PagerTabStrip
:
È possibile scorrere rapidamente avanti e indietro per vedere il numero di problema nel mazzo di schede flash che viene visualizzato nella parte superiore di ogni scheda flash.
Gestire l'input utente
FlashCardPager presenta una serie di schede flash basate su frammenti in un ViewPager
, ma non ha ancora un modo per rivelare la risposta per ogni problema. In questa sezione viene aggiunto un gestore eventi a FlashCardFragment
per visualizzare la risposta quando l'utente tocca il testo del problema della scheda flash.
Aprire FlashCardFragment.cs e aggiungere il codice seguente alla fine del OnCreateView
metodo subito prima che la vista venga restituita al chiamante:
questionBox.Click += delegate
{
Toast.MakeText(Activity.ApplicationContext,
"Answer: " + answer, ToastLength.Short).Show();
};
Questo Click
gestore eventi visualizza la risposta in un avviso popup visualizzato quando l'utente tocca .TextBox
La answer
variabile è stata inizializzata in precedenza quando le informazioni sullo stato sono state lette dal bundle passato a OnCreateView
. Compilare ed eseguire l'app, quindi toccare il testo del problema in ogni scheda flash per visualizzare la risposta:
FlashCardPager presentato in questa procedura dettagliata usa un MainActivity
derivato da FragmentActivity
, ma è anche possibile derivare MainActivity
da AppCompatActivity
(che fornisce anche il supporto per la gestione dei frammenti).
Riepilogo
Questa procedura dettagliata ha fornito un esempio dettagliato di come creare un'app di base ViewPager
basata su s Fragment
. Ha presentato un'origine dati di esempio contenente domande e risposte sulle schede flash, un ViewPager
layout per visualizzare le schede flash e una FragmentPagerAdapter
sottoclasse che connette l'oggetto ViewPager
all'origine dati. Per aiutare l'utente a spostarsi tra le schede flash, sono state incluse istruzioni che spiegano come aggiungere un PagerTabStrip
per visualizzare il numero di problema nella parte superiore di ogni pagina. Infine, il codice di gestione degli eventi è stato aggiunto per visualizzare la risposta quando l'utente tocca un problema di scheda flash.