我尝试了the sample code from the 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似乎根本没有任何状态信息保存代码。
答案 0 :(得分:116)
在ViewPager.setOffscreenPageLimit()
FragmentActivity
ViewPager pager = (ViewPager) findViewById(R.id.viewPager);
pager.setOffscreenPageLimit(2);
在How do I tell my custom FragmentPagerAdapter to stop destroying my fragments?
了解详情答案 1 :(得分:17)
只需在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);
来自您的代码
答案 2 :(得分:14)
<强>更新强> 在MyAdapter的getItem中,您将返回Fragment的新实例。 Android不会在每次刷卡时调用getItem。它只会调用getItem来获取一个新实例,但只要它们可用就会重用现有的实例。
关于演示的状态部分。我帮不了你我认为在Fragements / Activities中恢复状态的常规技术在这里适用,所以在ViewPager中加载它时没什么特别的(但我可能错了)。
答案 3 :(得分:13)
如果您覆盖
public void destroyItem(View container, int position, Object object)
不调用super,片段不会被销毁并将被重用。
答案 4 :(得分:3)
应该从FragmentStatePagerAdapter而不是FragmentPageAdapter扩展适配器,并且适配器将保持从位置到片段项的引用。在活动或片段父级上,为PageIndicator设置监听器OnPageChangeListener以检测已激活的片段项的位置并更新相关数据的状态。
关于片段项的数据状态,我认为应该从Activity或Fragement parent保存/恢复状态。
适配器可以添加一些代码,如下所示:
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);
}
...
}
希望得到这个帮助。
答案 5 :(得分:0)
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;
}