APIのサンプルコード を試しましたが、実際には機能しなかったため、独自に実装しました。
FragmentPagerSupport
public class FragmentPagerSupport extends FragmentActivity {
static final int NUM_ITEMS = 10;
MyAdapter mAdapter;
ViewPager mPager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mAdapter = new MyAdapter(getSupportFragmentManager());
Log.i("Pager", "mAdapter = " + mAdapter.toString());
mPager = (ViewPager)findViewById(R.id.pager);
if (mPager == null)
Log.i("Pager", "mPager = null");
else
Log.i("Pager", "mPager = " + mPager.toString());
Log.i("Pager", "Setting Pager Adapter");
mPager.setAdapter(mAdapter);
}
public static class MyAdapter extends FragmentPagerAdapter {
public MyAdapter(FragmentManager fm) {
super(fm);
Log.i("Pager", "MyAdapter constructor");
}
@Override
public int getCount() {
Log.i("Pager", "MyAdapter.getCount()");
return NUM_ITEMS;
}
@Override
public Fragment getItem(int position) {
Log.i("Pager", "MyAdapter.getItem()");
return TestFragment.newInstance(position);
}
}
public static class TestFragment extends Fragment {
public static TestFragment newInstance(int position) {
Log.i("Pager", "TestFragment.newInstance()");
TestFragment fragment = new TestFragment();
Bundle args = new Bundle();
args.putInt("position", position);
fragment.setArguments(args);
return fragment;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
Log.i("Pager", "TestFragment.onCreateView()");
LinearLayout layout = (LinearLayout)inflater.inflate(R.layout.fragment_item, null);
int position = getArguments().getInt("position");
TextView tv = (TextView)layout.findViewById(R.id.text);
tv.setText("Fragment # " + position);
tv.setTextColor(Color.WHITE);
tv.setTextSize(30);
return layout;
}
}
}
main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:orientation="vertical"
Android:layout_width="fill_parent"
Android:layout_height="fill_parent"
>
<Android.support.v4.view.ViewPager
Android:id="@+id/pager"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
/>
</LinearLayout>
fragment_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:orientation="vertical"
Android:layout_width="fill_parent"
Android:layout_height="fill_parent"
>
<TextView
Android:id="@+id/text"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:gravity="center"
Android:text="@string/hello"
/>
</LinearLayout>
私の質問は、ユーザーが左右にスワイプするたびに新しいFragment
インスタンスを作成する代わりに、フラグメントの状態を(何らかのデータ構造に)保存して復元する方法です。
API demo には、状態情報を保存するコードがまったくないようです。
FragmentActivity
でViewPager.setOffscreenPageLimit()
を使用します
ViewPager pager = (ViewPager) findViewById(R.id.viewPager);
pager.setOffscreenPageLimit(2);
fragmentpagerAdapterでこのメソッドをオーバーライドするだけです
_@Override
public void destroyItem(ViewGroup container, int position, Object object) {
// TODO Auto-generated method stub
super.destroyItem(ViewGroup container, int position, Object object);
}
_
削除super.destroyItem(ViewGroup container, int position, Object object);
あなたのコードから
更新: MyAdapterのgetItemで、フラグメントの新しいインスタンスを返します。 AndroidはスワイプごとにgetItemを呼び出しません。getItemを呼び出して新しいインスタンスを取得するだけですが、利用可能な限り既存のインスタンスを再利用します。
デモの状態部分について。私はあなたを助けることはできません。 Fragements/Activitiesで状態を復元するための通常の手法はここに適用されると思うので、ViewPagerに読み込むときに特別なことは何もありません(ただし、間違っている可能性があります)。
オーバーライドする場合
public void destroyItem(View container, int position, Object object)
superを呼び出さないと、フラグメントは破棄されず、再利用されます。
アダプターはFragmentPageAdapterではなくFragmentStatePagerAdapterから拡張する必要があり、アダプターは位置からフラグメントアイテムへの参照を保持します。アクティビティまたはフラグメントの親で、PageIndicatorのリスナーOnPageChangeListenerを設定して、フラグメントアイテムの位置がアクティブ化されたことを検出し、関連データの状態を更新します。
フラグメントアイテムのデータ状態については、ActivityまたはFragement親から状態を保存/復元する必要があると思います。
アダプターは、次のようなコードを追加できます。
public static class MyAdapter extends FragmentStatePagerAdapter {
private SparseArray<TestFragment> mPageReferenceMap
= new SparseArray<TestFragment>();
...
@Override
public Object instantiateItem(ViewGroup viewGroup, int position) {
Object obj = super.instantiateItem(viewGroup, position);
//Add the reference when fragment has been create or restore
if (obj instanceof TestFragment) {
TestFragment f= (TestFragment)obj;
mPageReferenceMap.put(position, f);
}
return obj;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
//Remove the reference when destroy it
mPageReferenceMap.remove(position);
super.destroyItem(container, position, object);
}
public TestFragment getFragment(int key) {
return mPageReferenceMap.get(key);
}
...
}
この助けを願っています。
似たような場所でつまずきました... FragmentPagerAdapter
にはフラグメントが5つしかなかったので、無駄なリロードを避けるために、フラグメントをアダプター内に保存したかったのです。
基本的に配列を作成し、getItem(position)
メソッドをオーバーライドする必要がありました。
private StoryListFragment[] fragmentsArray
= new StoryListFragment[getCount()];
public SectionsAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
if(fragmentsArray[position]!=null)
return fragmentsArray[position];
StoryListFragment storyListFragment = null;
switch(position){
case(0):
storyListFragment = StoryListFragment.newInstance(StoriesBank.NEWS);
break;
case(1):
storyListFragment = StoryListFragment.newInstance(StoriesBank.FEATURES);
break;
case(2):
storyListFragment= StoryListFragment.newInstance(StoriesBank.ARTS);
break;
}
fragmentsArray[position] = storyListFragment;
return storyListFragment;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
StoryListFragment fragment = (StoryListFragment) super.instantiateItem(container, position);
fragmentsArray[position] = fragment;
return fragment;
}