Android でページをスクロールするUIをつくる(ViewPager)

ViewPager を使って, スクロールして複数のViewを見るような
iOS ですと, ScrollView と, UIView のコンビネーションで作れたりするやつの紹介です。(Bloggerでも同じこと書きました)

English Version

android-support-v4.jar というjar に, ViewPager といった拡張クラスが入っています。これを使います。

ExtraPackに入っているものですので, 無ければSDK Managerを使ってインストールします。

さて, このViewPagerですが, スワイプ操作で, ページを移動していくような

使い方は,かなりListに似ています。Adapter(UIの構築などのコードつき), そのAdapterの操作でデータを管理, AdapterをViewPagerにセットすることでデータ表示させます。

さて今回作ったものはこんな感じです。(一部省略)

card1

card2

card3

まだありますが, 省略しときます。これらを左右のスワイプで移動させます。

さてこれを作るための手順です。

1. 全体のレイアウト(xml)
2. 各ページのレイアウト(xml)
3. Main のActivity
4. Adapter

1. 全体のレイアウト

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >

<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_weight="1" />

</LinearLayout>

2.各ページのレイアウト(xml)

ページに使うレイアウトを作りました。 card.xml という名前を付けました。画像とテキストが入っています。
ページのレイアウトを取り込みます。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
     
    <ImageView  android:id="@+id/img"
        android:contentDescription="@string/cardimg"
     android:layout_width="fill_parent"
     android:layout_marginTop="100dp"
     android:layout_height="wrap_content"
     android:layout_gravity="center"
    ></ImageView>
     
     
 <TextView android:id="@+id/word"
     android:layout_width="fill_parent"
     android:layout_height="match_parent"
     android:textSize="30sp"
     android:textAlignment="center"
     android:gravity="center"
     />
</LinearLayout>

3. Main のActivity

本体Activity のコードです。
ポイントは, ViewPager を取り出して, Adapter と, PageChangeListener を設定しているところです。
次回はUI変更のためのイベントの管理について説明します。

public class ViewPagerActivity extends Activity 
{
 private ViewPager viewPager;
  
 List<Persondata> list;
  
 @Override
 protected void onCreate(Bundle savedInstanceState) 
 {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.viewport);
   
  this.list = PersonDataGenerator.createPersonData();
   
  viewPager = (ViewPager) findViewById(R.id.viewpager);
  PagerAdapter pagerAdapter = new CardPagerAdapter(this, list);
  viewPager.setOnPageChangeListener(new PageChangeListener());
  viewPager.setAdapter(pagerAdapter);
 }
  
 class PageChangeListener extends SimpleOnPageChangeListener
 {
  @Override
  public void onPageSelected(int position) 
  {
   // Page change Operation!
  }
 }
}

4. Adapter

Adapter とは, 各ページのデータを設定したり, ページのリソースの処理をしたりするものです。ListView のAdapter とだいたい同じ 感じですが, PagerAdapter を extends する必要があります。
その実装例です。
@Override しているメソッドは必須です。 destroyItem は, Eclipse のQuickFix では登場しませんが, ないと, ページをめくった時に落ちますw。(Viewのメモリ管理をしているっぽい)

public class CardPagerAdapter extends PagerAdapter 
{
 LayoutInflater _inflater = null;
  
 List<Persondata> list;
  
 private TextView nameView;
  
 private ImageView charView;
  
  
 public CardPagerAdapter( Context context, List<Persondata> list )
 {
  super();
  _inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
  this.list = list;
 }
  
 @Override
 public Object instantiateItem(ViewGroup container, int position) 
 {
  LinearLayout layout = (LinearLayout)_inflater.inflate(R.layout.card, null);
   
  nameView = (TextView)layout.findViewById(R.id.word);
  nameView.setText(list.get(position).getName());
   
  charView = (ImageView)layout.findViewById(R.id.img);
  charView.setImageResource(list.get(position).getRes());
   
  container.addView(layout);
  return layout;
 }
  
 @Override
 public void destroyItem(ViewGroup container, int position, Object object) 
 {
  ((ViewPager) container).removeView((View) object);
 }
  
 
 @Override
 public int getCount() 
 {
  return list.size();
 }
 
 @Override
 public boolean isViewFromObject(View view, Object obj) 
 {
  return view.equals(obj);
 }
}

各ページのデータを外から注入して, 画像とテキストを設定します。
レイアウトは, XML から読み込んでいます(card.xml)

public class PersonData 
{
 private String name;
  
 private int res;
  
 public PersonData( String name, int res )
 {
  this.name = name;
  this.res = res;
 }
 
 public String getName() 
 {
  return name;
 }
 
 public void setName(String name) 
 {
  this.name = name;
 }
 
 public int getRes() 
 {
  return res;
 }
 
 public void setRes(int res) 
 {
  this.res = res;
 }
}
public class PersonDataGenerator 
{
 public static List<Persondata> createPersonData()
 {
  List<Persondata> res = new ArrayList<Persondata>();
   
  res.add(new PersonData("Sara Rukawa", R.drawable.tw_sar_eco));
  res.add(new PersonData("Aoi Hinomoto", R.drawable.tw_aoi_eco));
  res.add(new PersonData("Himeno Katsuragi", R.drawable.tw_him_eco));
  res.add(new PersonData("Sharuru Yoshino", R.drawable.tw_shr_eco));
  res.add(new PersonData("Rikka Morizono", R.drawable.tw_rik_eco));
   
  return res;
 }
}

画像のリソースと名前を定義しているだけですけどね。
これで, ページをスクロールして表示していくようなUIの出来上がりです。標準のライブラリだけできるのは, 素敵です。

さて, 見た目はこれでよいわけですが, こっからが難関です。各ページでイベントを拾います。では次回