ViewPager とフラグメント
ViewPager は、ゲスト ナビゲーションを実装できるレイアウト マネージャーです。 Gestural ナビゲーションを使用すると、ユーザーは左右にスワイプしてデータのページをステップスルーできます。 このガイドでは、データ ページとしてフラグメントを使用して、ViewPager でスワイプ可能な UI を実装する方法について説明します。
概要
ViewPager
は、多くの場合、 内の各ページのライフサイクルを管理しやすくするために、フラグメントと組み合わせて使用されます ViewPager
。 このチュートリアルでは、 ViewPager
を使用して FlashCardPager というアプリを作成し、フラッシュ カードに一連の数学の問題を示します。 各フラッシュ カードはフラグメントとして実装されます。 ユーザーはフラッシュ カードを左右にスワイプし、数学の問題をタップしてその答えを明らかにします。 このアプリは、Fragment
フラッシュ カードごとに インスタンスを作成し、 からFragmentPagerAdapter
派生したアダプターを実装します。 Viewpager と Views では、ほとんどの作業はライフサイクル メソッドでMainActivity
行われました。 FlashCardPager では、ほとんどの作業は、そのライフサイクル メソッドの 1 つで によってFragment
行われます。
このガイドでは、フラグメントの基本については説明しません。Xamarin.Android でフラグメントにまだ慣れていない場合は、「 フラグメント 」を参照してフラグメントの使用を開始してください。
アプリ プロジェクトを開始する
FlashCardPager という名前の新しい Android プロジェクトを作成します。 次に、NuGet パッケージ マネージャーを起動します (NuGet パッケージのインストールの詳細については、「 チュートリアル: プロジェクトに NuGet を含める」を参照してください)。 Viewpager と Views で説明されているように、Xamarin.Android.Support.v4 パッケージを見つけてインストールします。
サンプル データ ソースを追加する
FlashCardPager では、データ ソースは クラスによってFlashCardDeck
表されるフラッシュ カードのデッキです。このデータ ソースは、 に項目コンテンツをViewPager
提供します。 FlashCardDeck
には、数学の問題と回答の既製のコレクションが含まれています。 コンストラクターには FlashCardDeck
引数は必要ありません。
FlashCardDeck flashCards = new FlashCardDeck();
のフラッシュ カードFlashCardDeck
のコレクションは、各フラッシュ カードにインデクサーがアクセスできるように編成されています。 たとえば、次のコード行は、デッキの 4 番目のフラッシュ カード問題を取得します。
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
画面全体を占める を定義します。 はサポート ライブラリにパッケージ化されているためViewPager
、完全修飾名 android.support.v4.view.ViewPager を使用する必要があることに注意してください。 ViewPager
は 、Android サポート ライブラリ v4 からのみ使用できます。Android SDK では使用できません。
ViewPager を設定する
MainActivity.cs を編集し、次using
のステートメントを追加します。
using Android.Support.V4.View;
using Android.Support.V4.App;
MainActivity
から派生するようにクラス宣言をFragmentActivity
変更します。
public class MainActivity : FragmentActivity
MainActivity
は、フラグメントのサポートを管理する方法を知っているためFragmentActivity
、 ではなく からFragmentActivity
Activity
派生します。 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
UI フラグメントによって管理されます。 FlashCardFragment
のビューには、1 つのフラッシュ カードに含まれる情報が表示されます。 の FlashCardFragment
各インスタンスは、 によって ViewPager
ホストされます。
FlashCardFragment
のビューは、フラッシュカード問題のテキストを表示する で構成TextView
されます。 このビューでは、 を使用Toast
して、ユーザーがフラッシュ カード質問をタップしたときに回答を表示するイベント ハンドラーが実装されます。
FlashCardFragment レイアウトを作成する
実装する前 FlashCardFragment
に、そのレイアウトを定義する必要があります。 このレイアウトは、1 つのフラグメントのフラグメント コンテナー レイアウトです。 flashcard_layout.axml という名前の新しい Android レイアウトを Resources/layout に追加します。 Resources/layout/flashcard_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>
このレイアウトでは、単一のフラッシュ カード フラグメントが定義されます。各フラグメントは、大きな (100sp) フォントを使用して数学のTextView
問題を表示する で構成されます。 このテキストは、フラッシュ カードの垂直方向と水平方向の中央に配置されます。
初期 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
は、 でAndroid.Support.V4.App.Fragment
定義されている のサポート ライブラリ バージョンFragment
から派生しています。 コンストラクターが空であるため、ファクトリ メソッドを newInstance
使用してコンストラクターの代わりに新しい FlashCardFragment
を作成します。
ライフサイクル メソッドは OnCreateView
、 を作成して構成します TextView
。 フラグメント TextView
のレイアウトを拡張し、拡張された TextView
を呼び出し元に返します。 LayoutInflater
と ViewGroup
は に渡され OnCreateView
、レイアウトを膨らませることができます。 バンドル savedInstanceState
には、保存された OnCreateView
状態から を TextView
再作成するために を使用するデータが含まれています。
フラグメントのビューは、 の呼び出しによって明示的に inflater.Inflate
拡張されます。 引数はcontainer
ビューの親でありfalse
、フラグは、拡大されたビューをビューの親に追加しないようにインフレータに指示します (このチュートリアルで後述するアダプターのGetItem
メソッドを呼び出すとViewPager
追加されます)。
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
を変更して、渡された Bundle からこの情報を取得し、質問テキストを 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
データ ソースから情報を抽出し、それを使用して を作成 Fragment
して、 ViewPager
を表示します。
を実装する場合は 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.cs のクラスの先頭に次のFlashCardDeckAdapter
メンバー変数を追加します。
public FlashCardDeck flashCardDeck;
コンストラクターに次のコード行を FlashCardDeckAdapter
追加します。
this.flashCardDeck = flashCards;
このコード行には、 が使用する FlashCardDeck
インスタンスが FlashCardDeckAdapter
格納されます。
Count を実装する
実装はCount
比較的簡単です。フラッシュ カード デッキ内のフラッシュ カードの数を返します。 Count
を次のコードに置き換えます。
public override int Count
{
get { return flashCardDeck.NumCards; }
}
の FlashCardDeck
プロパティはNumCards
、データ セット内のフラッシュ カードの数 (フラグメントの数) を返します。
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
をレンダリングすると、フラッシュ カード デッキに存在する数学の問題文字列をposition
含む が表示されますTextBox
。Fragment
position
アダプターを ViewPager に追加する
が FlashCardDeckAdapter
実装されたので、 に追加 ViewPager
します。 MainActivity.cs で、 メソッドの末尾に次のコード行をOnCreate
追加します。
FlashCardDeckAdapter adapter =
new FlashCardDeckAdapter(SupportFragmentManager, flashCards);
viewPager.Adapter = adapter;
このコードは、 をインスタンス化し FlashCardDeckAdapter
、最初の引数で を SupportFragmentManager
渡します。 (FragmentActivity の プロパティはSupportFragmentManager
、 へのFragmentManager
参照を取得するために使用されます。の詳細については、「フラグメントのFragmentManager
管理」を参照してください)。
これでコア実装が完了しました。アプリをビルドして実行します。 次のスクリーンショットの左側に示すように、フラッシュ カード デッキの最初の画像が画面に表示されます。 左にスワイプして他のフラッシュ カードを表示し、右にスワイプしてフラッシュ カード デッキ内に戻ります。
ポケットベル インジケーターを追加する
この最小限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.cs の クラスに次のメソッドFlashCardDeckAdapter
を追加します。
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
に渡された Bundle から状態情報が読み取られたとき、変数は以前にOnCreateView
初期化されました。 アプリをビルドして実行し、各フラッシュ カードの問題のテキストをタップして、次の答えを確認します。
このチュートリアルで示す FlashCardPager では、 からFragmentActivity
派生した をMainActivity
使用しますが、 からAppCompatActivity
派生MainActivity
することもできます (フラグメントの管理のサポートも提供します)。 例を AppCompatActivity
表示するには、サンプル ギャラリーの FlashCardPager に関するページを参照してください。
まとめ
このチュートリアルでは、 を使用して基本 ViewPager
ベースのアプリをビルドする方法の詳細な例を Fragment
示しました。 フラッシュ カードの質問と回答、フラッシュ カードを表示するレイアウト、ViewPager
および FragmentPagerAdapter
データ ソースに を接続ViewPager
するサブクラスを含むデータ ソースの例を示しました。 ユーザーがフラッシュ カード内を移動できるように、各ページの上部に問題番号を表示する を PagerTabStrip
追加する方法を説明する手順が含まれていました。 最後に、ユーザーがフラッシュ カード問題をタップしたときに応答を表示するイベント処理コードが追加されました。