Android Tips #31 ViewPager で Fragment を使う

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

前回は ViewPager の基本的な使いかたについて解説しました。この ViewPager ですが、 View だけでなく Fragment をアイテムにすることができます! ということで今回は Support Package に用意されている FragmentPagerAdapter の使いかたを解説します。今回はサンプルは、下図のような伝統色Viewerをつくってみます。今回ももちろん Android 1.6 から動作します!

view_pager_fragment01

FragmentPagerAdapter を使って ViewPager をつくる

FragmentPagerAdapter は Fragment をアイテムとして表示する PagerAdapter です。各ページを Fragment にできます。このクラスを使って ViewPager を作ってみましょう。

1. Fragment をつくる

まずは ViewPager に表示するページの Fragment をつくります。Fragment には下記の情報が渡される想定です。

  • ページ番号
  • 伝統色名
  • 伝統色名の由来
  • 色タグ

レイアウトはこんな感じです。

fragment_traditional_color.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#cc0000"
    >
    
    <TextView 
        android:id="@+id/name_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="20dp"
        android:textSize="30sp"
        android:textStyle="bold"
        android:layout_alignParentTop="true"
        />
    
    <TextView 
        android:id="@+id/text_view"
        android:layout_width="500dp"
        android:layout_height="wrap_content"
        android:layout_below="@+id/name_view"
        android:layout_marginLeft="20dp"
        android:textSize="20sp"
        />
    
    <TextView 
        android:id="@+id/color_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginRight="10dp"
        android:textSize="80sp"
        android:textStyle="bold"
        android:textColor="#55ffffff"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        />
    
    <TextView 
        android:id="@+id/page_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="20dp"
        android:layout_marginBottom="10dp"
        android:textSize="24sp"
        android:layout_alignParentBottom="true"
        android:layout_alignParentLeft="true"
        />

</RelativeLayout>

あとは Fragment をつくります。Android 1.6 から対応させたい場合は android.support.v4.app.Fragment を必ず継承するようにしましょう。

TraditionalColorFragment.java

package jp.classmethod.android.sample.fragmentpager;

import android.graphics.Color;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import jp.classmethod.android.sample.traditionalcolorviewer.R;

/**
 * 色情報を表示する Fragment.
 */
public class TraditionalColorFragment extends Fragment {

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        // データを取得
        Bundle bundle = getArguments();
        int page = bundle.getInt("page");
        String color = bundle.getString("color");
        String name = bundle.getString("name");
        String description = bundle.getString("description");

        // View をつくる
        View layout = inflater.inflate(R.layout.fragment_traditional_color, container, false);
        layout.setBackgroundColor(Color.parseColor(color));
        
        // 色名
        TextView nameView = (TextView) layout.findViewById(R.id.name_view);
        nameView.setText(name);
        // 説明 (色名の由来)
        TextView textView = (TextView) layout.findViewById(R.id.text_view);
        textView.setText(description);
        // 色コード
        TextView colorView = (TextView) layout.findViewById(R.id.color_view);
        colorView.setText(color);
        // ページ
        TextView pageView = (TextView) layout.findViewById(R.id.page_view);
        pageView.setText(String.valueOf(page));

        return layout;
    }

}

ちなみに、以下のメソッドを使うと「#FF0000」のような String 文字列を色指定に使う int 型に変換できます。

int color = Color.parseColor(colorString);

2. FragmentPagerAdapter をつくる

次に FragmentPagerAdapter を継承したカスタムクラスをつくっていきます。 基本的な使いかたは PagerAdapter とあまり変わりませんが instantiateItem() は使わずに getItem() メソッド内で Fragment をつくります。 Fragment に値を渡すには setArguments() を使って Bundle で渡します。

TraditionalColorPagerAdapter.java

package jp.classmethod.android.sample.fragmentpager;

import java.util.ArrayList;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.util.SparseArrayCompat;

/**
 * 色情報の表示を管理する {@link FragmentPagerAdapter}.
 */
public class TraditionalColorPagerAdapter extends FragmentPagerAdapter {

    /** 色情報リスト. */
    private ArrayList<SparseArrayCompat<String>> mList;

    /**
     * コンストラクタ.
     * @param fm {@link FragmentManager}
     */
    public TraditionalColorPagerAdapter(FragmentManager fm) {
        super(fm);
        mList = new ArrayList<SparseArrayCompat<String>>();
    }

    @Override
    public Fragment getItem(int position) {

        // 対象ページの色情報を取得
        SparseArrayCompat<String> item = mList.get(position);

        // 色情報を Bundle にする
        Bundle bundle = new Bundle();
        bundle.putInt("page", position);
        bundle.putString("color", item.get(0));
        bundle.putString("name", item.get(1));
        bundle.putString("description", item.get(2));

        // Fragment をつくり Bundle をセットする
        TraditionalColorFragment frag = new TraditionalColorFragment();
        frag.setArguments(bundle);

        return frag;
    }

    @Override
    public int getCount() {
        return mList.size();
    }

    /**
     * 色情報を追加する.
     * @param item 色情報
     */
    public void add(SparseArrayCompat<String> item) {
        mList.add(item);
    }

    /**
     * 色情報をリストで追加する.
     * @param list 色情報リスト
     */
    public void addAll(ArrayList<SparseArrayCompat<String>> list) {
        mList.addAll(list);
    }

}

ちなみに、ここで使用している SparseArrayCompat は HashMap の代わりに使うことができる SparseArray の Support Package 版です。Android 1.6 (APIレベル4) から使うことができます!

3. FragmentActivity をつくる

最後に FragmentActivity を継承した Activity をつくります。FragmentPagerAdapter のコンストラクタ引数には FragmentManager を渡す必要があります。FragmentActivity#getSupportFragmentManager() で取得して渡します。

TraditionalColorActivity.java

package jp.classmethod.android.sample.fragmentpager;

import java.util.ArrayList;
import jp.classmethod.android.sample.traditionalcolorviewer.R;

import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.util.SparseArrayCompat;
import android.support.v4.view.ViewPager;

/**
 * 伝統色の情報を表示する {@link FragmentActivity}.
 */
public class TraditionalColorActivity extends FragmentActivity {
    
    /** 色情報を表示する {@link ViewPager}. */
    private ViewPager mViewPager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        // レイアウトをつくる
        setContentView(R.layout.activity_traditional_color);
        mViewPager = (ViewPager) findViewById(R.id.view_pager);
        
        // PagerAdapter をつくる
        FragmentManager fm = getSupportFragmentManager();
        TraditionalColorPagerAdapter adapter = new TraditionalColorPagerAdapter(fm);
        adapter.addAll(getColorList());
        
        // ViewPager にセットする
        mViewPager.setAdapter(adapter);
    }
    
    /**
     * 色情報リストを返す.
     * @return 色情報リスト
     */
    private ArrayList<SparseArrayCompat<String>> getColorList() {
        ArrayList<SparseArrayCompat<String>> list = new ArrayList<SparseArrayCompat<String>>();
        
        SparseArrayCompat<String> color1 = new SparseArrayCompat<String>();
        color1.append(0, "#727171");
        color1.append(1, "鈍色 (にびいろ)");
        color1.append(2, "かすかに緑や茶の色味を持つグレイに近い色。");
        SparseArrayCompat<String> color2 = new SparseArrayCompat<String>();
        color2.append(0, "#2792c3");
        color2.append(1, "縹 (はなだ)");
        color2.append(2, "藍の単一染めの純正な青色。「花田」とも書く。");
        SparseArrayCompat<String> color3 = new SparseArrayCompat<String>();
        color3.append(0, "#917347");
        color3.append(1, "朽葉色 (くちばいろ)");
        color3.append(2, "朽ちた落ち葉の色に似た褐色の、黄橙色(「黄唐茶」)。「朽葉四十八色」と言う言葉がある。");
        SparseArrayCompat<String> color4 = new SparseArrayCompat<String>();
        color4.append(0, "#3a5b52");
        color4.append(1, "虫襖 (むしあお)");
        color4.append(2, "玉虫の羽根の色に見るような、暗い青みの緑。「虫青」とも書く。");
        SparseArrayCompat<String> color5 = new SparseArrayCompat<String>();
        color5.append(0, "#f8b500");
        color5.append(1, "山吹色 (やまぶきいろ)");
        color5.append(2, "山吹の花の色のような、冴えた赤味の黄色。「黄金色」とも言う。");
        SparseArrayCompat<String> color6 = new SparseArrayCompat<String>();
        color6.append(0, "#e5abbe");
        color6.append(1, "石竹色 (せきちくいろ)");
        color6.append(2, "ナデシコ科の植物セキチクの花のような淡い赤色。");
        SparseArrayCompat<String> color7 = new SparseArrayCompat<String>();
        color7.append(0, "#e60026");
        color7.append(1, "紅蓮 (ぐれん)");
        color7.append(2, "盛んに燃え上がる炎の色。「紅蓮地獄(寒さのために皮膚が裂け血が流れ、紅の蓮の花のようになる)」を「紅の炎の燃え立つ所」と誤認したのが由来。");
        SparseArrayCompat<String> color8 = new SparseArrayCompat<String>();
        color8.append(0, "#007b43");
        color8.append(1, "常磐色 (ときわいろ)");
        color8.append(2, "スギなどの常緑樹の葉のようなくすんだ緑色。");
        
        list.add(color1);
        list.add(color2);
        list.add(color3);
        list.add(color4);
        list.add(color5);
        list.add(color6);
        list.add(color7);
        list.add(color8);
        
        return list;
    }

}

以上で完成です!!実行してみましょう♪

view_pager_fragment01

今回のサンプルでは 8 つの伝統色を登録してみました。さて、何の色でしょう?

view_pager_fragment02

ソースコード

今回も github にソースコードを公開しました。ぜひ参考にしてください!

suwa-yuki/TraditionalColorViewer

まとめ

前回の ViewPager の基本的な使いかたに続いて、今回は Fragment でつくる方法を解説しました。 公式リファレンスには「Fragment を使うほうがケースとして多い」と書かれているように ViewPager を使うケースとしては View より Fragment を使うほうが多いと思うので、ぜひ参考にしていただければと思います!

参考

  • 初代ポケモンのバッチの色だとやっと気付いた!!

  • Hideai Minami

    敬遠していたFragmentが分かるようになってきました!
    ありがとうございます(´∀`)