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の基本的な使い方は以下のページを参考にした。
参考
- AndroidTraining - 2.06. ListView と ViewPager
- ソフトウェア技術ドキュメントを勝手に翻訳 - 1.1 フラグメント
- Android Fragment を使う
- Android Fragment で setArguments() してるサンプルが多いのはなぜ?
- http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.0.1_r1/android/support/v4/app/FragmentPagerAdapter.java#51
- 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); } } }