ViewPager UIの変更

前回の引き続きまして, ViewPagerを見ていきます。 English

前回は, Android でページをスクロールするUIをつくる という題で, スワイプして移動するViewをViewPagerを使って実装しました。

さて, ここから何かしらのイベントを取って, ViewPager内のUIを変更するにはどうするか, ちょっとした工夫が必要になります。

変更に関しては, 2つの変更があります。

1. UIもしくはデータの変更

2. データの追加・削除]

今回は1を扱います。次回2を扱います。

1.ですが, ちょっとした工夫が必要になります。

card1

今回は, このページの画像をタップすると, 名前の部分を”Favorites!” と変更するイベントを追加しましょう。

cardclick

手順です。

1. Adapter に, イベントのコードを追加(引数として渡したいものは, final で定義して保存しておきましょう)

2. イベント内にListenerを作成(interface), イベントメソッドを入れておく

3. Activity側に2で作成したリスナを実装する

4. タグをもとに, UIを取り出して変更する + データそのものも変更しておく(destroyで再作成されるので)

なんだか言葉で書くとややこしいですが, コードを見ていきましょう。

Adapter

public class CardPagerAdapter extends PagerAdapter 
{
	LayoutInflater _inflater = null;
	
	List<PersonData> list;
	
	private TextView nameView;
	
	private ImageView charView;
	
	// listener
	private ClickPagerImgListerner listener;
	
	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);
		
		String name = list.get(position).getName();
		
		nameView.setText(list.get(position).getName());
		nameView.setTag(name);			// Add tag
		
		charView = (ImageView)layout.findViewById(R.id.img);
		charView.setImageResource(list.get(position).getRes());
		
		charView.setClickable(true);
		
		final int index = position;
		charView.setOnClickListener(new OnClickListener() 
		{
			@Override
			public void onClick(View v) 
			{
				//Log.d("", index);
				if ( listener != null )
				{
					listener.change(index);
				}
			}
		});
		
		
		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);
	}
	
	public void setListener( ClickPagerImgListerner listener )
	{
		this.listener = listener;
	}
}

前回の部分と違うのは, listenerが入っていること, 画像にClickイベントを追加し, リスナーのメソッドを呼び出していること。
TextViewにタグをつけているところです。タグは後で, Activityから, Viewを取得するのに使っています。

そのリスナーです

Listener

public interface ClickPagerImgListerner 
{
	public void change( int position );
}

ただのインターフェイスです。これをActivityに実装することで, AdapterとActivityをinterface でゆるくつなぎます。

Activity

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

	@Override
	public void change(int position) 
	{
		TextView nameView = (TextView)viewPager.findViewWithTag(list.get(position).getName());
		nameView.setText("Favorites!");
		list.get(position).setName("Favorites");
	}

}

さて, ここがメインです。リスナーで拾ったイベントがここに帰ってきます。 changeというやつです。
UIをタグを使って引っ張り出し, テキストを変更します。 そしてAdapterにセットしたデータも変更します(destroyされたときに, データをもとにUIを作り直すので)
notifyDataSetChangedは呼ばなくても大丈夫。データの数が変わらない時は効果ありません。

イベントを拾って動的にViewPager内のデータの変更ができます。

AWTとか, Swingとかと似たようなテクニックですね。
次回はデータの数を変更します。