Поделиться через


ViewPager с фрагментами

ViewPager — это диспетчер макетов, который позволяет реализовать навигацию gestural. Навигация gestural позволяет пользователю проводите пальцем влево и вправо на страницы данных. В этом руководстве объясняется, как реализовать экранируемый пользовательский интерфейс с помощью ViewPager, используя фрагменты в качестве страниц данных.

Обзор

ViewPagerчасто используется в сочетании с фрагментами, чтобы упростить управление жизненным циклом каждой страницы.ViewPager В этом пошаговом руководстве используется для создания приложения с именем FlashCardPager, ViewPager которое представляет ряд математических проблем в флэш-карта. Каждая вспышка карта реализуется как фрагмент. Пользователь проводит пальцем влево и вправо через вспышку карта и нажимает на математические проблемы, чтобы показать свой ответ. Это приложение создает Fragment экземпляр для каждого флэш-карта и реализует адаптер, производный от FragmentPagerAdapter. В Viewpager и Views большая часть работы была выполнена в MainActivity методах жизненного цикла. В FlashCardPager большая часть работы будет выполнена Fragment одним из методов жизненного цикла.

В этом руководстве не рассматриваются основы фрагментов. Если вы еще не знакомы с фрагментами в Xamarin.Android, ознакомьтесь с фрагментами, которые помогут вам приступить к работе с фрагментами.

Запуск проекта приложения

Создайте новый проект Android с именем FlashCardPager. Затем запустите диспетчер пакетов NuGet (дополнительные сведения об установке пакетов NuGet см. в пошаговом руководстве. Включение NuGet в проект). Найдите и установите пакет Xamarin.Android.Support.v4 , как описано в Viewpager и Views.

Добавление примера источника данных

В FlashCardPager источник данных представляет собой колоду флэш-карта, представленных FlashCardDeck классом. Этот источник данных предоставляет содержимое ViewPager элемента. FlashCardDeck содержит готовую коллекцию математических задач и ответов. Конструктору FlashCardDeck не требуются аргументы:

FlashCardDeck flashCards = new FlashCardDeck();

Коллекция карта флэш-памяти организована таким образом, чтобы доступ к каждой флэш-карта FlashCardDeck можно получить индексатором. Например, следующая строка кода извлекает четвертую проблему флэш-карта в палубе:

string problem = flashCardDeck[3].Problem;

Эта строка кода получает соответствующий ответ на предыдущую проблему:

string answer = flashCardDeck[3].Answer;

Поскольку сведения о FlashCardDeck реализации не относятся к пониманию ViewPager, FlashCardDeck код не указан здесь. Исходный код FlashCardDeck доступен по FlashCardDeck.cs. Скачайте исходный файл (или скопируйте и вставьте код в новый файл FlashCardDeck.cs ) и добавьте его в проект.

Создание макета ViewPager

Откройте файл Resources/layout/Main.axml и замените его содержимое следующим 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>

Этот XML-код определяет ViewPager , который занимает весь экран. Обратите внимание, что необходимо использовать полное имя android.support.v4.view.ViewPager , так как ViewPager упаковано в библиотеку поддержки. ViewPager доступен только из библиотеки поддержки Android версии 4. Она недоступна в пакете SDK для Android.

Настройка ViewPager

Измените MainActivity.cs и добавьте следующие using инструкции:

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

Измените MainActivity объявление класса таким образом, чтобы оно было производным от FragmentActivity:

public class MainActivity : FragmentActivity

MainActivity является производным отFragmentActivity (а не Activity) потому, что FragmentActivity знает, как управлять поддержкой фрагментов. Замените метод OnCreate следующим кодом:

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

Этот код выполняет следующие действия:

  1. Задает представление из ресурса макета Main.axml .

  2. Извлекает ссылку на ViewPager макет.

  3. Создает экземпляр нового FlashCardDeck источника данных.

При сборке и запуске этого кода вы увидите дисплей, похожий на следующий снимок экрана:

Снимок экрана: приложение FlashCardPager с пустым ViewPager

На этом этапе он пуст, ViewPager так как не хватает фрагментов, которые используются для заполнения ViewPager, и он не имеет адаптера для создания этих фрагментов из данных в FlashCardDeck.

В следующих разделах создается для реализации функциональных FlashCardFragment возможностей каждой флэш-карта и FragmentPagerAdapter создается для подключения ViewPager к фрагментам, созданным из данных.FlashCardDeck

Создание фрагмента

Каждый флэш-карта управляется фрагментом FlashCardFragmentпользовательского интерфейса. FlashCardFragmentВ представлении отображаются сведения, содержащиеся в одной флэш-карта. Каждый экземпляр FlashCardFragment будет размещен в объекте ViewPager. FlashCardFragmentПредставление будет состоять из TextView представления, отображающего текст проблемы флэш-карта. В этом представлении будет реализован обработчик событий, который используется Toast для отображения ответа, когда пользователь нажимает флэш-карта вопрос.

Создание макета FlashCardFragment

Перед FlashCardFragment реализацией необходимо определить его макет. Этот макет представляет собой макет контейнера фрагмента для одного фрагмента. Добавьте новый макет Android в resources/layout с именем flash карта_layout.axml. Откройте resources/layout/flash карта_layout.axml и замените его содержимое следующим кодом:

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

Этот макет определяет один фрагмент флэш-карта; каждый фрагмент состоит из TextView математических проблем с использованием большого шрифта (100sp). Этот текст находится в центре по вертикали и горизонтально на карта вспышки.

Создание начального класса FlashCardFragment

Добавьте новый файл с именем FlashCardFragment.cs и замените его содержимое следующим кодом:

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

Этот код заглушает важное Fragment определение, которое будет использоваться для отображения флэш-карта. Обратите внимание, что FlashCardFragment является производным от версии библиотеки поддержки, определенной Fragment в Android.Support.V4.App.Fragment. Конструктор пуст, чтобы newInstance метод фабрики использовался для создания нового FlashCardFragment вместо конструктора.

Метод OnCreateView жизненного цикла создает и настраивает TextView. Он увеличивает макет для фрагмента TextView и возвращает раздувленный TextView вызывающему объекту. LayoutInflater и ViewGroup передаются OnCreateView таким образом, чтобы он смог раздуть макет. Пакет savedInstanceState содержит данные, которые OnCreateView используются для повторного создания TextView из сохраненного состояния.

Представление фрагмента явно раздувается вызовом inflater.Inflate. Аргумент container является родительским элементом представления, и false флаг предписывает надувной элементу воздержаться от добавления раздуваемого представления в родительский элемент представления (он будет добавлен при ViewPager вызове метода адаптера GetItem далее в этом пошаговом руководстве).

Добавление кода состояния в FlashCardFragment

Как и действие, фрагмент имеет то Bundle , что используется для сохранения и извлечения его состояния. В FlashCardPager это Bundle используется для сохранения вопроса и ответа текста связанной флэш-карта. В FlashCardFragment.cs добавьте следующие Bundle ключи в начало FlashCardFragment определения класса:

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

Измените newInstance метод фабрики таким образом, чтобы он создал Bundle объект и использовал приведенные выше ключи для хранения переданного текста вопроса и ответа в фрагменте после создания экземпляра:

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

Измените метод OnCreateView жизненного цикла фрагмента, чтобы получить эти сведения из переданного пакета и загрузить текст вопроса в 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;
}

Переменная answer здесь не используется, но она будет использоваться позже при добавлении кода обработчика событий в этот файл.

Создание адаптера

ViewPagerиспользует объект контроллера адаптера, который находится между ViewPager источником данных (см. иллюстрацию в статье "Адаптер ViewPager"). Для доступа к этим данным требуется предоставить пользовательский адаптер, ViewPager производный от PagerAdapter. Так как в этом примере используются фрагменты, он использует производный FragmentPagerAdapterFragmentPagerAdapter от PagerAdapter. FragmentPagerAdapter представляет каждую страницу в качестве Fragment постоянного хранения в диспетчере фрагментов до тех пор, пока пользователь может вернуться на страницу. По мере того как пользователь проводит пальцем по страницамViewPagerFragmentPagerAdapter, извлекает информацию из источника данных и использует ее для ViewPager отображенияFragment.

При реализации FragmentPagerAdapterнеобходимо переопределить следующее:

  • Count — свойство только для чтения, которое возвращает количество доступных представлений (страниц).

  • GetItem — возвращает фрагмент, отображаемый для указанной страницы.

Добавьте новый файл с именем FlashCardDeckAdapter.cs и замените его содержимое следующим кодом:

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

Этот код заглушает основную FragmentPagerAdapter реализацию. В следующих разделах каждый из этих методов заменяется рабочим кодом. Цель конструктора — передать диспетчер FlashCardDeckAdapterфрагментов конструктору базового класса.

Реализация конструктора адаптера

Когда приложение создает экземплярFlashCardDeckAdapter, он предоставляет ссылку на диспетчер фрагментов и экземпляр.FlashCardDeck Добавьте следующую переменную-член в верхнюю часть FlashCardDeckAdapter класса в FlashCardDeckAdapter.cs:

public FlashCardDeck flashCardDeck;

Добавьте в конструктор следующую строку кода FlashCardDeckAdapter :

this.flashCardDeck = flashCards;

Эта строка кода сохраняет FlashCardDeck экземпляр, который FlashCardDeckAdapter будет использоваться.

Реализация счетчика

Реализация Count относительно проста: она возвращает количество карта флэш-памяти в палубе флэш-карта. Замените Count следующим кодом:

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

Свойство NumCardsFlashCardDeck возвращает количество карта флэш-памяти (количество фрагментов) в наборе данных.

Реализация GetItem

Метод GetItem возвращает фрагмент, связанный с заданной позицией. При GetItem вызове позиции в палубе флэш-карта возвращается настроенная FlashCardFragment для отображения проблемы флэш-карта на этой позиции. Замените метод GetItem следующим кодом:

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

Этот код выполняет следующие действия:

  1. Ищет строку математических проблем в палубе FlashCardDeck для указанной позиции.

  2. Ищет строку ответа в палубе FlashCardDeck для указанной позиции.

  3. Вызывает метод newInstanceфабрикиFlashCardFragment, передавая проблему флэш-карта и строки ответа.

  4. Создает и возвращает новый флэш-картаFragment, содержащий текст вопроса и ответа для этой позиции.

ViewPager При отрисовке Fragmentpositionв ней отображается TextBox строка математических задач, которая находится в position карта палубе флэш-карта.

Добавление адаптера в ViewPager

Теперь, когда FlashCardDeckAdapter реализация реализована, пришло время добавить его в ViewPager. В MainActivity.cs добавьте следующую строку кода в конец OnCreate метода:

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

Этот код создает экземпляр FlashCardDeckAdapter, передаваемого SupportFragmentManager в первом аргументе. (Свойство SupportFragmentManager FragmentActivity используется для получения ссылки на FragmentManager фрагменты . Дополнительные сведения об FragmentManagerэтом см. в разделе "Управление фрагментами".)

Базовая реализация завершена — сборка и запуск приложения. На экране появится первое изображение флэш-карта колоды, как показано слева на следующем снимке экрана. Проводите пальцем влево, чтобы увидеть больше карта флэш-памяти, а затем проводите пальцем вправо, чтобы перейти к флэш-карта палубе:

Примеры снимков экрана приложения FlashCardPager без индикаторов пейджера

Добавление индикатора pager

Эта минимальная ViewPager реализация отображает каждый флэш-карта в палубе, но он не указывает, где пользователь находится в палубе. Следующий шаг — добавить PagerTabStrip. Пользователь PagerTabStrip сообщает пользователю о том, какой номер проблемы отображается и предоставляет контекст навигации, отображая подсказку о предыдущих и следующих карта флэш-памяти.

Откройте resources/layout/Main.axml и добавьте в PagerTabStrip макет:

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

При сборке и запуске приложения должно отображаться пустое PagerTabStrip в верхней части каждого флэш-карта:

Закрытие PagerTabStrip без текста

Отображение заголовка

Чтобы добавить заголовок на каждой вкладке страницы, реализуйте GetPageTitleFormatted метод в адаптере. ViewPager вызовы GetPageTitleFormatted (если реализованы), чтобы получить строку заголовка, описывающую страницу в указанной позиции. Добавьте следующий метод в FlashCardDeckAdapter класс в FlashCardDeckAdapter.cs:

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

Этот код преобразует позицию в флэш-карта колоде в номер проблемы. Результирующая строка преобразуется в Java String , который возвращается в ViewPager. При запуске приложения с этим новым методом каждая страница отображает номер проблемы в PagerTabStrip:

Снимок экрана: FlashCardPager с номером проблемы, отображаемым над каждой страницей

Проводите пальцем вправо и вперед, чтобы увидеть номер проблемы в карта палубе флэш-памяти, отображаемой в верхней части каждой вспышки карта.

Обработка ввода пользователем

FlashCardPager представляет ряд фрагментов флэш-карта в , ViewPagerно еще не имеет способа выявить ответ на каждую проблему. В этом разделе обработчик событий добавляется в FlashCardFragment ответ, когда пользователь нажимает на текст проблемы флэш-карта.

Откройте FlashCardFragment.cs и добавьте следующий код в конец OnCreateView метода непосредственно перед возвратом представления вызывающему объекту:

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

Этот Click обработчик событий отображает ответ в всплывающем элементе, который отображается при касании TextBoxпользователя. Переменная answer была инициализирована ранее, когда сведения о состоянии считывались из пакета, переданного в OnCreateView. Создайте и запустите приложение, а затем коснитесь текста проблемы на каждом флэш-карта, чтобы увидеть ответ:

Снимок экрана приложения FlashCardPager, когда математические проблемы касаются

FlashCardPager, представленный в этом пошаговом руководстве, использует производный MainActivity от FragmentActivity, но вы также можете получить производный MainActivity от AppCompatActivity (который также обеспечивает поддержку управления фрагментами).

Итоги

В этом пошаговом руководстве представлен пошаговый пример создания базового ViewPagerприложения на основе s Fragment. В нем представлен пример источника данных, содержащего флэш-карта вопросы и ответы, ViewPager макет для отображения флэш-карта и FragmentPagerAdapter подкласса, который подключается ViewPager к источнику данных. Чтобы помочь пользователю перемещаться по флэш-карта, были включены инструкции, которые объясняют, как добавить PagerTabStrip номер проблемы в верхней части каждой страницы. Наконец, код обработки событий был добавлен, чтобы отобразить ответ, когда пользователь нажимает на проблему флэш-карта.