Edited at

ViewPagerで現在のページのFragmentを取得する方法

More than 3 years have passed since last update.

ViewPagerはスワイプでViewを移動するUIを実現するコンポーネントです.ViewPager#setAdapter()PagerAdapterを継承したAdapterをセットして使います.基本的な使い方はこちらを参照してください.

各スクリーンはFragmentになっていることが推奨されていますので,ページ全体をスワイプで移動したいとき,スワイプでFragmentを切り替えるのに使うのがFragmentPagerAdapterです.最近はタブの切り替えなんかもスワイプで出来るようにするので,皆さんもよく使うと思います.


現在表示中のFragmentをAdapterから取得したい

ViewPagerが現在表示してくれているFragmentを,Adapterから取得する方法について書きます.参考にしたページはこちらになります.

- [1] android - Getting the current Fragment instance in the viewpager - Stack Overflow

- [2] Android for professionals: Get current visible fragment page in a ViewPager

- [3] FragmentPagerAdapterからFragmentを参照するときはinstantiateItemを - 江戸一番のジャスタウェイ職人のブログ

ViewPagerにはgetCurrentItem()メソッドがあり,これは現在のページのインデックスを取得出来ます.インデックスがとれたから「PagerAdapter#getItem(index)で取得出来るやん」とやると罠にハマります.getItem()といういかにもなメソッド名ですが,おそらく皆さんが実装したgetItem()は大体こんなカンジになってると思います.

public Fragment getItem(int position) {

return HogeFragment.newInstance(position);
}

然るべきFragmentインスタンスを新たに生成してreturnしています.なので現在表示中のFragmentインスタンスとは別のインスタンスです.当然,ViewPagerにはアタッチされていません.getItem()というメソッド名はひっかけなのです.

さて,当初の目的を達成する方法は以下です.


方法1 FragmentManagerから取得する

FragmentはActivity(またはFragment)のFragmentManagerが管理していますので,インスタンスに固有のタグをセットしておけばFragmentManager#findFragmentByTag()メソッドで取得出来ます.また,セットしなくてもフレームワークが内部的にセットしていて,それを利用して取得することも出来ます.[1]

fragmentManager.findFragmentByTag("android:switcher:" + R.id.pager + ":" + position);


方法2 Adapterのメンバ変数に保持しておく

Adapterのメンバ変数にmCurrentFragmentのような変数を定義して,ここで管理する方法です.

これの実装方法にもいくつかパターンがあります.FragmentPagerAdapter#setPrimaryItem()メソッドの第三引数に渡ってくるObjectをmCurrentFragmentに入れておく方法が簡単そう.[2]

public class MyPagerAdapter extends FragmentPagerAdapter {

private Fragment mCurrentFragment;

...

@Override
public void setPrimaryItem(ViewGroup container, int position, Object object) {
if (mCurrentFragment != object) {
mCurrentFragment = (Fragment) object;
}
super.setPrimaryItem(container, position, object);
}

public Fragment getCurrentFragment() {
return mCurrentFragment;
}
}


方法3 instantiateItemを使う

最後.特に問題にならないのであればこの方法を使うのが良いと思います.[3]

public class MyPagerAdapter extends FragmentPagerAdapter {

public Fragment findFragmentByPosition(ViewPager viewPager,
int position) {
return (Fragment) instantiateItem(viewPager, position);
}
}

以上です.