Udostępnij za pośrednictwem


Obiekt ViewPager z fragmentami

ViewPager to menedżer układów, który umożliwia implementowanie nawigacji gesturalnej. Nawigacja gestyuralna umożliwia użytkownikowi przesunięcie w lewo i w prawo, aby przejść przez strony danych. W tym przewodniku wyjaśniono, jak zaimplementować interfejs użytkownika z możliwością przesunięcia za pomocą programu ViewPager przy użyciu fragmentów jako stron danych.

Omówienie

ViewPager jest często używany w połączeniu z fragmentami, dzięki czemu łatwiej jest zarządzać cyklem życia każdej strony w obiekcie ViewPager. W tym przewodniku ViewPager jest używany do tworzenia aplikacji o nazwie FlashCardPager , która przedstawia serię problemów matematycznych na kartach flash. Każda karta flash jest implementowana jako fragment. Użytkownik przesuwa palcem w lewo i w prawo przez karty flash i dotyka problemu matematycznego, aby ujawnić swoją odpowiedź. Ta aplikacja tworzy Fragment wystąpienie dla każdej karty flash i implementuje adapter pochodzący z FragmentPagerAdapterklasy . W widoku i widokach większość pracy wykonano w MainActivity metodach cyklu życia. W programie FlashCardPager większość pracy będzie wykonywana przez Fragment jedną z metod cyklu życia.

Ten przewodnik nie obejmuje podstaw fragmentów — jeśli nie znasz jeszcze fragmentów na platformie Xamarin.Android, zobacz Fragmenty ułatwiające rozpoczęcie pracy z fragmentami.

Uruchamianie projektu aplikacji

Utwórz nowy projekt systemu Android o nazwie FlashCardPager. Następnie uruchom Menedżer pakietów NuGet (aby uzyskać więcej informacji na temat instalowania pakietów NuGet, zobacz Przewodnik: dołączanie pakietu NuGet w projekcie). Znajdź i zainstaluj pakiet Xamarin.Android.Support.v4 zgodnie z opisem w temacie Viewpager and Views(Widoki).

Dodawanie przykładowego źródła danych

W programie FlashCardPager źródło danych jest talii kart flash reprezentowanych przez klasę FlashCardDeck ; to źródło danych dostarcza ViewPager zawartość elementu. FlashCardDeck zawiera gotową kolekcję problemów matematycznych i odpowiedzi. Konstruktor FlashCardDeck nie wymaga żadnych argumentów:

FlashCardDeck flashCards = new FlashCardDeck();

Kolekcja kart flash w programie FlashCardDeck jest zorganizowana tak, aby dostęp do każdej karty flash był dostępny przez indeksator. Na przykład następujący wiersz kodu pobiera czwarty problem z kartą flash na pokładzie:

string problem = flashCardDeck[3].Problem;

Ten wiersz kodu pobiera odpowiadającą odpowiedź na poprzedni problem:

string answer = flashCardDeck[3].Answer;

Ponieważ szczegóły FlashCardDeck implementacji nie są istotne dla zrozumienia ViewPager, FlashCardDeck kod nie jest wymieniony tutaj. Kod źródłowy, który FlashCardDeck ma być dostępny w FlashCardDeck.cs. Pobierz ten plik źródłowy (lub skopiuj i wklej kod do nowego pliku FlashCardDeck.cs ) i dodaj go do projektu.

Tworzenie układu viewPager

Otwórz plik Resources/layout/Main.axml i zastąp jego zawartość następującym kodem 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>

Ten kod XML definiuje element ViewPager , który zajmuje cały ekran. Należy pamiętać, że należy użyć w pełni kwalifikowanej nazwy android.support.v4.view.ViewPager , ponieważ ViewPager jest spakowana w bibliotece pomocy technicznej. ViewPager Jest dostępny tylko z biblioteki pomocy technicznej systemu Android w wersji 4; nie jest dostępny w zestawie ANDROID SDK.

Konfigurowanie programu ViewPager

Edytuj MainActivity.cs i dodaj następujące using instrukcje:

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

Zmień deklarację MainActivity klasy, aby pochodziła z FragmentActivityklasy :

public class MainActivity : FragmentActivity

MainActivity pochodzi zFragmentActivity elementu (zamiast Activity), ponieważ FragmentActivity wie, jak zarządzać obsługą fragmentów. Zastąp metodę OnCreate poniższym kodem:

protected override void OnCreate(Bundle bundle)
{
    base.OnCreate(bundle);
    SetContentView(Resource.Layout.Main);
    ViewPager viewPager = FindViewById<ViewPager>(Resource.Id.viewpager);
    FlashCardDeck flashCards = new FlashCardDeck();
}

Ten kod powoduje wykonanie następujących czynności:

  1. Ustawia widok z zasobu układu Main.axml .

  2. Pobiera odwołanie do ViewPager elementu z układu.

  3. Tworzy wystąpienie nowego FlashCardDeck źródła danych.

Podczas tworzenia i uruchamiania tego kodu powinien zostać wyświetlony ekran podobny do poniższego zrzutu ekranu:

Zrzut ekranu aplikacji FlashCardPager z pustym programem ViewPager

W tym momencie wartość jest pusta, ViewPager ponieważ brakuje fragmentów, które są używane do wypełniania elementu , i brakuje karty do tworzenia tych fragmentów z danych w narzędziu ViewPagerFlashCardDeck.

W poniższych sekcjach element jest FlashCardFragment tworzony w celu zaimplementowania funkcji każdej karty flash, a element FragmentPagerAdapter jest tworzony w celu nawiązania połączenia z ViewPager fragmentami utworzonymi na podstawie danych w obiekcie FlashCardDeck.

Tworzenie fragmentu

Każda karta flash będzie zarządzana przez fragment interfejsu użytkownika o nazwie FlashCardFragment. FlashCardFragmentW widoku będą wyświetlane informacje zawarte w jednej karcie flash. Każde wystąpienie programu będzie hostowane FlashCardFragment przez program ViewPager. FlashCardFragmentWidok będzie składać się z elementu TextView , który wyświetla tekst problemu karty flash. Ten widok zaimplementuje procedurę obsługi zdarzeń, która używa elementu Toast , aby wyświetlić odpowiedź, gdy użytkownik naciągnie pytanie karty flash.

Tworzenie układu FlashCardFragment

Przed FlashCardFragment wdrożeniem należy zdefiniować jego układ. Ten układ jest układem kontenera fragmentu dla pojedynczego fragmentu. Dodaj nowy układ systemu Android do folderu Resources/layout o nazwie flashcard_layout.axml. Otwórz plik Resources/layout/flashcard_layout.axml i zastąp jego zawartość następującym kodem:

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

Ten układ definiuje pojedynczy fragment karty flash; każdy fragment składa się z elementu TextView , który wyświetla problem matematyczny przy użyciu dużej czcionki (100sp). Ten tekst jest wyśrodkowany w pionie i poziomo na karcie flash.

Tworzenie początkowej klasy FlashCardFragment

Dodaj nowy plik o nazwie FlashCardFragment.cs i zastąp jego zawartość następującym kodem:

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

Ten kod wyróżnia podstawową Fragment definicję, która będzie używana do wyświetlania karty flash. Należy pamiętać, że FlashCardFragment pochodzi z wersji biblioteki pomocy technicznej zdefiniowanej Fragment w pliku Android.Support.V4.App.Fragment. Konstruktor jest pusty, aby newInstance metoda fabryki była używana do utworzenia nowego FlashCardFragment zamiast konstruktora.

Metoda OnCreateView cyklu życia tworzy i konfiguruje element TextView. Zawyża układ fragmentu TextView i zwraca zawyżone TextView do elementu wywołującego. LayoutInflater i ViewGroup są przekazywane do OnCreateView , aby można było zawyżać układ. Pakiet savedInstanceState zawiera dane używane OnCreateView do ponownego utworzenia TextView elementu z zapisanego stanu.

Widok fragmentu jest jawnie zawyżony przez wywołanie metody inflater.Inflate. Argument container jest elementem nadrzędnym widoku, a false flaga nakazuje nadmuchiwaczowi, aby powstrzymał się od dodania zawyżonego widoku do elementu nadrzędnego widoku (zostanie on dodany, gdy ViewPager wywołanie metody adaptera GetItem zostanie dodane w dalszej części tego przewodnika).

Dodawanie kodu stanu do funkcji FlashCardFragment

Podobnie jak działanie, fragment zawiera Bundle element , którego używa do zapisywania i pobierania stanu. W programie FlashCardPager służy to Bundle do zapisywania tekstu pytania i odpowiedzi dla skojarzonej karty flash. W FlashCardFragment.cs dodaj następujące Bundle klucze na początku FlashCardFragment definicji klasy:

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

Zmodyfikuj metodę fabryki newInstance , tak aby tworzyła Bundle obiekt i używa powyższych kluczy do przechowywania przekazanego pytania i tekstu odpowiedzi w fragmentacji po utworzeniu wystąpienia:

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

Zmodyfikuj metodę OnCreateView cyklu życia fragmentu, aby pobrać te informacje z przekazanego pakietu i załadować tekst pytania do elementu 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;
}

Zmienna answer nie jest używana w tym miejscu, ale będzie używana później, gdy kod programu obsługi zdarzeń zostanie dodany do tego pliku.

Tworzenie adaptera

ViewPagerużywa obiektu kontrolera karty, który znajduje się między ViewPager źródłem danych i (zobacz ilustrację w artykule Adapter ViewPager). Aby uzyskać dostęp do tych danych, ViewPager wymagane jest podanie niestandardowej karty pochodzącej z PagerAdapterprogramu . Ponieważ w tym przykładzie użyto fragmentów, użyto elementu FragmentPagerAdapterFragmentPagerAdapter pochodzi z PagerAdapterklasy . FragmentPagerAdapter reprezentuje każdą stronę jako Fragment trwale przechowywaną w menedżerze fragmentów tak długo, jak użytkownik może wrócić do strony. Gdy użytkownik szybko przesuwa strony ViewPagerobiektu , FragmentPagerAdapter wyodrębnia informacje ze źródła danych i używa ich do utworzenia FragmentViewPager elementu do wyświetlenia.

Podczas implementowania elementu FragmentPagerAdapternależy zastąpić następujące elementy:

  • Count — właściwość tylko do odczytu, która zwraca liczbę dostępnych widoków (stron).

  • GetItem — zwraca fragment do wyświetlenia dla określonej strony.

Dodaj nowy plik o nazwie FlashCardDeckAdapter.cs i zastąp jego zawartość następującym kodem:

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

Ten kod wyróżnia podstawową FragmentPagerAdapter implementację. W poniższych sekcjach każda z tych metod jest zastępowana kodem roboczym. Celem konstruktora jest przekazanie menedżera fragmentów do FlashCardDeckAdapterkonstruktora klasy bazowej .

Implementowanie konstruktora adaptera

Gdy aplikacja tworzy wystąpienie FlashCardDeckAdapterobiektu , dostarcza odwołanie do menedżera fragmentów i wystąpienie FlashCardDeckelementu . Dodaj następującą zmienną składową na początku FlashCardDeckAdapter klasy w FlashCardDeckAdapter.cs:

public FlashCardDeck flashCardDeck;

Dodaj następujący wiersz kodu do konstruktora FlashCardDeckAdapter :

this.flashCardDeck = flashCards;

Ten wiersz kodu przechowuje FlashCardDeck wystąpienie, którego będzie używać FlashCardDeckAdapter .

Implementowanie liczby

Implementacja Count jest stosunkowo prosta: zwraca liczbę kart flash w talii karty flash. Zastąp Count ciąg następującym kodem:

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

Właściwość NumCards zwraca FlashCardDeck liczbę kart flash (liczba fragmentów) w zestawie danych.

Implementowanie polecenia GetItem

Metoda GetItem zwraca fragment skojarzony z daną pozycją. Po GetItem wywołaniu pozycji w talii karty flash zwraca skonfigurowany do wyświetlania problemu z kartą FlashCardFragment flash w tej pozycji. Zastąp metodę GetItem poniższym kodem:

public override Android.Support.V4.App.Fragment GetItem(int position)
{
    return (Android.Support.V4.App.Fragment)
        FlashCardFragment.newInstance (
            flashCardDeck[position].Problem, flashCardDeck[position].Answer);
}

Ten kod powoduje wykonanie następujących czynności:

  1. Wyszukuje ciąg problemu matematyczny w FlashCardDeck pokładzie dla określonej pozycji.

  2. Wyszukuje ciąg odpowiedzi w FlashCardDeck pokładzie dla określonej pozycji.

  3. Wywołuje metodę newInstancefabryki FlashCardFragment , przekazując problem z kartą flash i ciągi odpowiedzi.

  4. Tworzy i zwraca nową kartę Fragment flash zawierającą tekst pytania i odpowiedzi dla tej pozycji.

Gdy renderuje element ViewPager at position, wyświetla TextBox on zawierający ciąg problemu matematyczny znajdujący się w position Fragment talii karty flash.

Dodawanie adaptera do programu ViewPager

Teraz, gdy FlashCardDeckAdapter element jest zaimplementowany, nadszedł czas, aby dodać go do elementu ViewPager. W MainActivity.cs dodaj następujący wiersz kodu na końcu OnCreate metody:

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

Ten kod tworzy wystąpienie FlashCardDeckAdaptermetody , przekazując SupportFragmentManager element w pierwszym argumencie. (Właściwość SupportFragmentManager FragmentActivity służy do uzyskiwania odwołania do FragmentManager obiektu — aby uzyskać więcej informacji o FragmentManagerobiekcie , zobacz Zarządzanie fragmentami).

Podstawowa implementacja została ukończona — skompiluj i uruchom aplikację. Na ekranie powinien zostać wyświetlony pierwszy obraz pokładu karty flash, jak pokazano po lewej stronie na następnym zrzucie ekranu. Przesuń palcem w lewo, aby zobaczyć więcej kart flash, a następnie przesuń palcem w prawo, aby wrócić przez pokład karty flash:

Przykładowe zrzuty ekranu aplikacji FlashCardPager bez wskaźników pager

Dodawanie wskaźnika pagera

Ta minimalna ViewPager implementacja wyświetla każdą kartę flash na pokładzie, ale nie wskazuje na to, gdzie użytkownik znajduje się w talii. Następnym krokiem jest dodanie elementu PagerTabStrip. Narzędzie PagerTabStrip informuje użytkownika o numerze problemu i udostępnia kontekst nawigacji, wyświetlając wskazówkę poprzednich i następnych kart flash.

Otwórz plik Resources/layout/Main.axml i dodaj element PagerTabStrip do układu:

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

Podczas kompilowania i uruchamiania aplikacji powinna zostać wyświetlona pusta PagerTabStrip w górnej części każdej karty flash:

Zbliżenie elementu PagerTabStrip bez tekstu

Wyświetlanie tytułu

Aby dodać tytuł do każdej karty strony, zaimplementuj GetPageTitleFormatted metodę na karcie adaptera. ViewPager wywołania GetPageTitleFormatted (jeśli zaimplementowano) w celu uzyskania ciągu tytułu opisującego stronę w określonej pozycji. Dodaj następującą metodę do FlashCardDeckAdapter klasy w FlashCardDeckAdapter.cs:

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

Ten kod konwertuje położenie na talii karty flash na numer problemu. Wynikowy ciąg jest konwertowany na język Java String , który jest zwracany do elementu ViewPager. Po uruchomieniu aplikacji przy użyciu tej nowej metody każda strona wyświetla numer problemu w pliku PagerTabStrip:

Zrzuty ekranu programu FlashCardPager z numerem problemu wyświetlanym nad każdą stroną

Możesz przesunąć palcem wstecz i z powrotem, aby zobaczyć numer problemu w talii karty flash, która jest wyświetlana u góry każdej karty flash.

Obsługa danych wejściowych użytkownika

FlashCardPager przedstawia serię kart flash opartych na fragmentach w ViewPagerobiekcie , ale nie ma jeszcze sposobu na ujawnienie odpowiedzi dla każdego problemu. W tej sekcji do elementu zostanie dodana FlashCardFragment procedura obsługi zdarzeń, aby wyświetlić odpowiedź, gdy użytkownik naciągnie tekst problemu karty flash.

Otwórz FlashCardFragment.cs i dodaj następujący kod na końcu OnCreateView metody tuż przed zwróceniem widoku do obiektu wywołującego:

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

Ta Click procedura obsługi zdarzeń wyświetla odpowiedź w wyskakujących wyskakujących komunikatach, gdy użytkownik naciągnie TextBoxelement . Zmienna answer została zainicjowana wcześniej, gdy informacje o stanie zostały odczytane z pakietu przekazanego do OnCreateViewelementu . Skompiluj i uruchom aplikację, a następnie naciśnij tekst problemu na każdej karcie flash, aby zobaczyć odpowiedź:

Zrzuty ekranu aplikacji FlashCardPager wyskakujące po naciśnięciu problemu matematycznego

Program FlashCardPager przedstawiony w tym przewodniku używa elementu pochodzącego MainActivity z FragmentActivityelementu , ale można również pochodzić MainActivity z AppCompatActivity elementu (który zapewnia również obsługę zarządzania fragmentami).

Podsumowanie

W tym przewodniku przedstawiono szczegółowy przykład tworzenia podstawowej ViewPageraplikacji Fragmentopartej na języku s. Przedstawiono przykładowe źródło danych zawierające pytania i odpowiedzi dotyczące karty flash, ViewPager układ umożliwiający wyświetlenie kart flash oraz podklasę FragmentPagerAdapter łączącą źródło ViewPager danych. Aby ułatwić użytkownikowi nawigowanie po kartach flash, zawarto instrukcje objaśniające sposób dodawania elementu w PagerTabStrip celu wyświetlenia numeru problemu w górnej części każdej strony. Na koniec dodano kod obsługi zdarzeń, aby wyświetlić odpowiedź, gdy użytkownik naciągnie problem z kartą flash.