viewpager - tabs android
Guardar estado de fragmento en ViewPager (6)
El adaptador debe extenderse desde FragmentStatePagerAdapter en lugar de FragmentPageAdapter y el adaptador mantendrá la referencia de posición a elemento de fragmento. En la actividad o fragmento principal, configure el detector OnPageChangeListener para PageIndicator para detectar la posición del elemento de fragmento que se ha activado y actualice el estado de los datos relacionados.
Sobre el estado de los datos del elemento de fragmento, creo que debería guardar / restaurar el estado de actividad o padre de Fragement.
El adaptador puede agregar algunos códigos de la siguiente manera:
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);
}
...
}
Espero que esto ayude.
Probé el código de muestra de la API y realmente no funcionó, así que implementé el mío:
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>
Mi pregunta es: en lugar de crear una nueva instancia de Fragment
cada vez que el usuario pase de izquierda a derecha, ¿cómo guardo el estado de un fragmento (en cierta estructura de datos) y luego lo restauro?
La demostración de la API no parece tener ningún código de ahorro de información de estado.
Si anulas
public void destroyItem(View container, int position, Object object)
sin llamar super, el fragmento no será destruido y será reutilizado.
Tropecé en un terreno similar ... Quería mantener mis fragmentos guardados en mi adaptador para evitar una recarga inútil, ya que solo tenía 5 fragmentos en FragmentPagerAdapter
.
Básicamente tuve que crear una matriz y anular el 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;
}
Use ViewPager.setOffscreenPageLimit()
en FragmentActivity
ViewPager pager = (ViewPager) findViewById(R.id.viewPager);
pager.setOffscreenPageLimit(2);
Ver más en ¿Cómo le digo a mi FragmentPagerAdapter personalizado que deje de destruir mis fragmentos?
simplemente anule este método en FragmentpagerAdapter
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
// TODO Auto-generated method stub
super.destroyItem(ViewGroup container, int position, Object object);
}
eliminar super.destroyItem(ViewGroup container, int position, Object object);
de tu código
Actualización: en el getItem de MyAdapter, devuelve una nueva instancia de su Fragment. Android no llamará a getItem en cada golpe. Solo llamará a getItem para obtener una nueva instancia, pero reutilizará las instancias existentes siempre que estén disponibles.
Acerca de la parte de estado de la demostración. No puedo ayudarte Creo que las técnicas normales para restaurar el estado en Fragements / Activities se aplican aquí, por lo que no es nada especial cuando se carga en un ViewPager (pero podría estar equivocado).