共用方式為


使用片段的 ViewPager

ViewPager 是一個版面配置管理員,可讓您實作 Gestural 流覽。 Gestural 瀏覽可讓使用者向左撥動和向右撥動,以逐步瀏覽數據頁面。 本指南說明如何使用 Fragments 作為數據頁,使用 ViewPager 實作可撥動 UI。

概觀

ViewPager 通常會與片段搭配使用,以便更輕鬆地管理 中 ViewPager每個頁面的生命週期。 在本逐步解說中, ViewPager 用來建立名為 FlashCardPager 的應用程式,以在快閃卡上呈現一系列數學問題。 每個快閃卡都會實作為片段。 使用者透過快閃卡向左和向右撥動,並點選數學問題以顯示其答案。 此應用程式會 Fragment 為每個快閃卡建立實例,並實作衍生自 FragmentPagerAdapter的配接器。 在 Viewpager 和 Views 中,大部分的工作都是在生命週期方法中 MainActivity 完成。 在 FlashCardPager 中,大部分的工作將由 在其其中一個生命週期方法中完成 Fragment

本指南並未涵蓋片段的基本概念 – 如果您還不熟悉 Xamarin.Android 中的片段,請參閱 片段 以協助您開始使用片段。

啟動應用程式專案

建立名為 FlashCardPager 的新 Android 專案。 接下來,啟動 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 支援連結庫 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 (而非 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 具現化為數據源。

當您建置並執行此程式代碼時,您應該會看到類似下列螢幕快照的顯示:

具有空白 ViewPager 的 FlashCardPager 應用程式的螢幕快照

此時,ViewPager是空的,因為它缺少使用的片段填入 ViewPager,而且缺少從 FlashCardDeck 中的數據建立這些片段的配接器。

在下列各節中, FlashCardFragment 會建立 來實作每個快閃卡的功能,而 FragmentPagerAdapter 會建立 ,以將 連接到 ViewPager 從 中的數據建立的 FlashCardDeck片段。

建立片段

每個快閃卡都會由稱為 FlashCardFragment的UI片段管理。 FlashCardFragment的檢視會顯示單一快閃卡所包含的資訊。 的每個實例 FlashCardFragment 都會由 ViewPager裝載。 FlashCardFragment的檢視將包含顯示 TextView 快閃卡問題文字的 。 此檢視會實作事件處理程式,該事件處理程式會在用戶點選快閃卡問題時使用 Toast 來顯示答案。

建立 FlashCardFragment 版面配置

必須先 FlashCardFragment 定義其配置,才能實作。 此配置是單一片段的片段容器配置。 將新的 Android 版面配置新增至名為 flashcard_layout.axml 的資源/版面配置。 開啟 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>

此配置會定義單一快閃卡片片段;每個片段都是由 , 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衍生自 中Android.Support.V4.App.Fragment定義的支持連結庫版本Fragment。 建構函式是空的 newInstance ,因此 Factory 方法可用來建立新的 FlashCardFragment ,而不是建構函式。

OnCreateView生命週期方法會建立及設定 TextView。 它會擴充片段的配置 TextView ,並將膨脹 TextView 傳回給呼叫端。 LayoutInflaterViewGroup 會傳遞至 OnCreateView ,使其可以擴充版面配置。 套件savedInstanceState組合包含用來從儲存狀態重新建立 TextView 的數據OnCreateView

片段的檢視是由的呼叫 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修改 Factory 方法,讓它建立 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 衍生自 PagerAdapterFragmentPagerAdapter 表示每個頁面, Fragment 只要使用者可以返回頁面,就會持續保留在片段管理員中。 當使用者撥動 頁面 ViewPager時,會 FragmentPagerAdapter 從資料源擷取資訊,並使用它來建立 FragmentViewPager 來顯示 。

當您實作 FragmentPagerAdapter時,必須覆寫下列專案:

  • Count – 只讀屬性,可傳回可用的檢視數 (pages) 數目。

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

此程式碼會執行下列操作:

  1. 查閱甲板中指定位置的 FlashCardDeck 數學問題字串。

  2. 查閱甲板中指定位置的 FlashCardDeck 回應字串。

  3. FlashCardFragment呼叫 Factory 方法newInstance,傳入快閃卡問題和回應字串。

  4. 建立並傳回新的快閃卡片 Fragment ,其中包含該位置的問答文字。

當 呈現ViewPagerFragmentposition時,它會顯示 TextBox ,其中包含位於position快閃卡片牌組中的數學問題字串。

將配接器新增至 ViewPager

現在已 FlashCardDeckAdapter 實作 ,現在可以將它新增至 ViewPager。 在 MainActivity.cs中,將下列程式代碼行新增至 方法的 OnCreate 結尾:

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

此程式代碼會具現化 FlashCardDeckAdapter,傳入 SupportFragmentManager 第一個自變數中的 。 SupportFragmentManager(FragmentActivity 的 屬性是用來取得 的FragmentManager參考 – 如需 的詳細資訊FragmentManager,請參閱管理片段

核心實作現已完成 – 建置並執行應用程式。 您應該會看到快閃卡片牌組的第一張影像出現在畫面上,如下一個螢幕快照中的左側所示。 向左撥動以查看更多快閃卡片,然後向右撥動以透過快閃卡片牌組移動:

沒有呼叫器指標的 FlashCardPager 應用程式的範例螢幕快照

新增呼叫器指標

這個最小 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));
}

此程式代碼會將快閃卡片牌組中的位置轉換為問題編號。 產生的字串會轉換成傳回至的ViewPagerJavaString。 當您使用這個新方法執行應用程式時,每個頁面都會在 中 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,但您也可以衍生MainActivityAppCompatActivity (這也提供管理片段的支援)。

摘要

本逐步解說提供如何使用 s 建置基本 ViewPager型應用程式的 Fragment逐步範例。 它呈現了包含快閃卡問題和解答的範例數據源、 ViewPager 顯示快閃卡的配置,以及 FragmentPagerAdapter 聯機 ViewPager 至數據源的子類別。 為了協助用戶流覽快閃卡,包含說明如何新增 PagerTabStrip 以在每個頁面頂端顯示問題號碼的指示。 最後,新增事件處理程序代碼,以在用戶點選快閃卡問題時顯示答案。