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();
}
Этот код выполняет следующие действия:
Задает представление из ресурса макета Main.axml .
Извлекает ссылку на
ViewPager
макет.Создает экземпляр нового
FlashCardDeck
источника данных.
При сборке и запуске этого кода вы увидите дисплей, похожий на следующий снимок экрана:
На этом этапе он пуст, 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
. Так как в этом примере используются фрагменты, он использует производный FragmentPagerAdapter
FragmentPagerAdapter
от PagerAdapter
.
FragmentPagerAdapter
представляет каждую страницу в качестве Fragment
постоянного хранения в диспетчере фрагментов до тех пор, пока пользователь может вернуться на страницу. По мере того как пользователь проводит пальцем по страницамViewPager
FragmentPagerAdapter
, извлекает информацию из источника данных и использует ее для 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; }
}
Свойство NumCards
FlashCardDeck
возвращает количество карта флэш-памяти (количество фрагментов) в наборе данных.
Реализация 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);
}
Этот код выполняет следующие действия:
Ищет строку математических проблем в палубе
FlashCardDeck
для указанной позиции.Ищет строку ответа в палубе
FlashCardDeck
для указанной позиции.Вызывает метод
newInstance
фабрикиFlashCardFragment
, передавая проблему флэш-карта и строки ответа.Создает и возвращает новый флэш-карта
Fragment
, содержащий текст вопроса и ответа для этой позиции.
ViewPager
При отрисовке Fragment
position
в ней отображается TextBox
строка математических задач, которая находится в position
карта палубе флэш-карта.
Добавление адаптера в ViewPager
Теперь, когда FlashCardDeckAdapter
реализация реализована, пришло время добавить его в ViewPager
. В MainActivity.cs добавьте следующую строку кода в конец OnCreate
метода:
FlashCardDeckAdapter adapter =
new FlashCardDeckAdapter(SupportFragmentManager, flashCards);
viewPager.Adapter = adapter;
Этот код создает экземпляр FlashCardDeckAdapter
, передаваемого SupportFragmentManager
в первом аргументе. (Свойство SupportFragmentManager
FragmentActivity используется для получения ссылки на FragmentManager
фрагменты . Дополнительные сведения об FragmentManager
этом см. в разделе "Управление фрагментами".)
Базовая реализация завершена — сборка и запуск приложения. На экране появится первое изображение флэш-карта колоды, как показано слева на следующем снимке экрана. Проводите пальцем влево, чтобы увидеть больше карта флэш-памяти, а затем проводите пальцем вправо, чтобы перейти к флэш-карта палубе:
Добавление индикатора 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
в верхней части каждого флэш-карта:
Отображение заголовка
Чтобы добавить заголовок на каждой вкладке страницы, реализуйте 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 представляет ряд фрагментов флэш-карта в , ViewPager
но еще не имеет способа выявить ответ на каждую проблему. В этом разделе обработчик событий добавляется в FlashCardFragment
ответ, когда пользователь нажимает на текст проблемы флэш-карта.
Откройте FlashCardFragment.cs и добавьте следующий код в конец OnCreateView
метода непосредственно перед возвратом представления вызывающему объекту:
questionBox.Click += delegate
{
Toast.MakeText(Activity.ApplicationContext,
"Answer: " + answer, ToastLength.Short).Show();
};
Этот Click
обработчик событий отображает ответ в всплывающем элементе, который отображается при касании TextBox
пользователя. Переменная answer
была инициализирована ранее, когда сведения о состоянии считывались из пакета, переданного в OnCreateView
. Создайте и запустите приложение, а затем коснитесь текста проблемы на каждом флэш-карта, чтобы увидеть ответ:
FlashCardPager, представленный в этом пошаговом руководстве, использует производный MainActivity
от FragmentActivity
, но вы также можете получить производный MainActivity
от AppCompatActivity
(который также обеспечивает поддержку управления фрагментами).
Итоги
В этом пошаговом руководстве представлен пошаговый пример создания базового ViewPager
приложения на основе s Fragment
. В нем представлен пример источника данных, содержащего флэш-карта вопросы и ответы, ViewPager
макет для отображения флэш-карта и FragmentPagerAdapter
подкласса, который подключается ViewPager
к источнику данных. Чтобы помочь пользователю перемещаться по флэш-карта, были включены инструкции, которые объясняют, как добавить PagerTabStrip
номер проблемы в верхней части каждой страницы. Наконец, код обработки событий был добавлен, чтобы отобразить ответ, когда пользователь нажимает на проблему флэш-карта.