江戸一番のジャスタウェイ職人のブログ

江戸一番のジャスタウェイ職人

FragmentPagerAdapterからFragmentを参照するときはinstantiateItemを

以下の構成でスワイプできるタブビューを実装していたけれどActivity上のボタンやメニューからFragment内のListViewなど操作したく試行錯誤していた。

  • android.support.v4.app.FragmentActivity
  • android.support.v4.app.FragmentManager
  • android.support.v4.app.FragmentPagerAdapter
  • android.support.v4.app.ListFragment
  • android.support.v4.view.ViewPager

Fragmentの基本的な使い方は以下のページを参考にした。

参考

MyPagerAdapterのgetItemはFragmentPagerAdapterが内部的に使うものでActivityから呼ぶものではなく、またこの時のインスタンをどこか変数に置いて参照したりするとメモリからFragment上のViewが破棄された後にViewが空のFragmentを掴んでぬるぽで落ちたりする。

ActivityからFragmentを取得するときはinstantiateItemを使うと必ず取得できるのでこれを使うことにした。

元々FragmentPagerAdapter内部に任意のpositionのtagを取得するメソッドがあるがprivateなので参照できず、これがpublicならfindFragmentByTagが使えた、Stack Overflowではそのprivateなメソッドをコピペで持ってくるライフハックが紹介されていてなんのためのprivateなのかよくわからないことになっていた。

FragmentPagerAdapterの用例でgetItemとgetCountは大抵どこの記事でも紹介されているが(無いと動かないので)instantiateItemで生成済みのFragmentを参照できることに言及している記事が少なめだったので備忘録を兼ねて書いておきます。

public class MainActivity extends FragmentActivity {

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    /**
     * スワイプで動かせるタブを実装するのに最低限必要な実装
     */
    MyPagerAdapter pagerAdapter = new MyPagerAdapter(
        getSupportFragmentManager());
    ViewPager viewPager = (ViewPager) findViewById(R.id.pager);
    viewPager.setAdapter(pagerAdapter);
  }

  public class MyPagerAdapter extends FragmentPagerAdapter {

    public MyPagerAdapter(FragmentManager fm) {
      super(fm);
    }

    @Override
    public Fragment getItem(int position) {
      Fragment fragment = null;
      switch (position) {
      case 0:
        // ListFragmentを継承したFragment
        fragment = (Fragment) new HogeFragment();
        break;
      case 1:
        // ListFragmentを継承したFragment
        fragment = (Fragment) new FooFragment();
        break;
      }
      return fragment;
    }

    @Override
    public int getCount() {
      // タブ数
      return 2;
    }

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