Compatibility Package r3のViewPagerとPagerAdapterを使ってみる

AndroidのCompatibility Package r3にViewPagerとPagerAdapterなるものが追加されていました。

これはどんなものかというと、Androidのホーム画面のように、スワイプ動作によって表示するViewを切り替えられるViewです。

すでにViewSwitcherやViewFlipperなるViewは存在しますが、それらとは違い、ページ切り替え用のイベントを実装する必要はありません。
※ViewSwitcherやViewFlipperの場合はActivityのonTouchEventあたりをオーバーライドしてページ切り替えを実装します。

また、ホーム画面と同じような動作をしますので、スワイプを始めると、切り替え中の2つのViewが同時に表示されます。
以下のような感じです。

・スワイプ前

・スワイプ中



サンプルでは、Fragmentを使用した例があったので、Fragmentを使用しない場合を試してみました。
※Compatibility Packageを使うならFragmentを使った方が良いとは思いますが。

で、使い方。

手順1
Compatibility Package r3をダウンロードしてビルドパスに追加します。

手順2
以下のようなレイアウトファイルを作成します。
main.xml(アクティビティ用のレイアウト)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="vertical"
  android:layout_width="match_parent"
  android:layout_height="match_parent">
  <android.support.v4.view.ViewPager
    android:id="@+id/pager"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
  </android.support.v4.view.ViewPager>
</LinearLayout>

page.xml(View用)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="vertical"
  android:layout_width="match_parent"
  android:layout_height="match_parent">
  <TextView
    android:id="@+id/text"
    android:layout_weight="1"
    android:layout_width="match_parent"
    android:layout_height="0dip" />
  <EditText
    android:layout_weight="1"
    android:layout_width="match_parent"
    android:layout_height="0dip" />
</LinearLayout>

手順3
PagerAdapterの実装クラスを作成
private class MyAdapter extends PagerAdapter {
  private static final int NUM_VIEW = 5;
  private final LayoutInflater mInflater;

  public MyAdapter(final Context context) {
    mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
  }

  @Override
  public void destroyItem(final View collection, final int position, final Object view) {
    ((ViewPager) collection).removeView((View) view);
  }

  @Override
    public void finishUpdate(final View collection) {
  }

  @Override
  public int getCount() {
    return NUM_VIEW;
  }

  @Override
  public Object instantiateItem(final View collection, final int position) {
    final ViewPager pager = (ViewPager) collection;
    final View view = mInflater.inflate(R.layout.page, pager, false);
    final TextView text = (TextView) view.findViewById(R.id.text);
    // サンプルの画像用に背景色とテキスト色を変更する
    if (position % 2 == 0) {
      view.setBackgroundColor(0xff000000);
    } else {
      view.setBackgroundColor(0xffaaaaaa);
      text.setTextColor(0xff000000);
    }
    text.setText("position = " + position);
    pager.addView(view, 0);
    return view;
  }

  @Override
  public boolean isViewFromObject(final View view, final Object object) {
    return view == (View) object;
  }

  @Override
  public void restoreState(final Parcelable parcel, final ClassLoader classLoader) {
  }

  @Override
  public Parcelable saveState() {
    return null;
  }

  @Override
  public void startUpdate(final View collection) {
  }
}

手順4
ActivityでViewPagerにPagerAdapterの実装クラスをセットする
  // ・・・
  private ViewPager mViewPager;
  private MyAdapter mAdapter;

  @Override
  public void onCreate(final Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    mAdapter = new MyAdapter(this);
    mViewPager = (ViewPager) findViewById(R.id.pager);
    mViewPager.setAdapter(mAdapter);
  }
  // ・・・

と、このような感じです。


一応、難点もありまして。
Viewの切り替えごとにinstantiateItemが呼ばれるため、前に表示したViewの状態を保存する必要がある場合は、何かしらの仕掛けをする必要があります。
※Viewをキャッシュしておいて、positionに応じたViewを表示するようにすればなんとか。

また、ViewSwitcherやViewFlipperと違い、最後のView(最初のView)を表示しているときに、次のView(前のView)を表示することはできません。
※ViewSwitcherやViewFlipperでは、最後のView(最初のView)でshowNext(showPrev)を呼ぶと、
最初(最後)のViewを表示することができます。

コメント