Estoy usando la compatibilidad v4 ViewPager en Android. My FragmentActivity tiene una gran cantidad de datos que se mostrarán de diferentes maneras en diferentes páginas en mi ViewPager. Hasta ahora solo tengo 3 instancias del mismo ListFragment, pero en el futuro tendré 3 instancias de ListFragments diferentes. ViewPager está en una pantalla de teléfono vertical, las listas no están una al lado de la otra.
Ahora, un botón en ListFragment inicia una actividad de página completa separada (a través de FragmentActivity), que regresa y FragmentActivity modifica los datos, los guarda y luego intenta actualizar todas las vistas en su ViewPager. Es aquí, donde estoy atrapado.
public class ProgressMainActivity extends FragmentActivity
{
MyAdapter mAdapter;
ViewPager mPager;
@Override
public void onCreate(Bundle savedInstanceState)
{
...
mAdapter = new MyAdapter(getSupportFragmentManager());
mPager = (ViewPager) findViewById(R.id.viewpager);
mPager.setAdapter(mAdapter);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
...
updateFragments();
...
}
public void updateFragments()
{
//Attempt 1:
//mAdapter.notifyDataSetChanged();
//mPager.setAdapter(mAdapter);
//Attempt 2:
//HomeListFragment fragment = (HomeListFragment) getSupportFragmentManager().findFragmentById(mAdapter.fragId[0]);
//fragment.updateDisplay();
}
public static class MyAdapter extends FragmentPagerAdapter implements
TitleProvider
{
int[] fragId = {0,0,0,0,0};
public MyAdapter(FragmentManager fm)
{
super(fm);
}
@Override
public String getTitle(int position){
return titles[position];
}
@Override
public int getCount(){
return titles.length;
}
@Override
public Fragment getItem(int position)
{
Fragment frag = HomeListFragment.newInstance(position);
//Attempt 2:
//fragId[position] = frag.getId();
return frag;
}
@Override
public int getItemPosition(Object object) {
return POSITION_NONE; //To make notifyDataSetChanged() do something
}
}
public class HomeListFragment extends ListFragment
{
...
public static HomeListFragment newInstance(int num)
{
HomeListFragment f = new HomeListFragment();
...
return f;
}
...
Ahora, como puede ver, mi primer intento fue notificar aDataSetChanged en todo el FragmentPagerAdapter, y esto demostró actualizar los datos a veces, pero otros obtuve una IllegalStateException: no se puede realizar esta acción después de onSaveInstanceState.
Mi segundo intento invocó el intento de llamar a una función de actualización en mi ListFragment, pero getId en getItem devolvió 0. Según los documentos que probé por
adquirir una referencia al Fragment de FragmentManager, usando findFragmentById () o findFragmentByTag ()
¡pero no sé la etiqueta o la identificación de mis Fragmentos! Tengo un android: id = "@ + id / viewpager" para ViewPager, y un android: id = "@ android: id / list" para mi ListView en el diseño ListFragment, pero no creo que sean útiles.
Entonces, ¿cómo puedo: a) actualizar todo el ViewPager de forma segura de una sola vez (idealmente, devolver al usuario a la página en la que estaba antes): está bien que el usuario vea el cambio de vista. O preferiblemente, b) llame a una función en cada ListFragment afectado para actualizar el ListView manualmente.
Cualquier ayuda sería gratamente aceptada!
fuente
null
por fragmento.FragmentPagerAdaper
pero fallaFragmentStatePagerAdaper
(Fragment.getTag()
siempre regresanull
.La respuesta de Barkside funciona con,
FragmentPagerAdapter
pero no funcionaFragmentStatePagerAdapter
, porque no establece etiquetas en los fragmentos a los que pasaFragmentManager
.Con
FragmentStatePagerAdapter
lo que parece que podemos pasar, utilizando suinstantiateItem(ViewGroup container, int position)
llamada. Devuelve la referencia al fragmento en la posiciónposition
. SiFragmentStatePagerAdapter
ya contiene una referencia al fragmento en cuestión,instantiateItem
solo devuelve la referencia a ese fragmento y no llamagetItem()
para instanciarlo nuevamente.Entonces, supongamos que actualmente estoy mirando el fragmento # 50, y quiero acceder al fragmento # 49. Ya que están cerca, hay una buena posibilidad de que el # 49 ya esté instanciado. Entonces,
fuente
FragmentStatePagerAdapter
, usar el código anterior cona.instantiateItem(viewPager, viewPager.getCurrentItem());
(para deshacerse de los 49) como lo propone @ mblackwell8 funciona perfectamente.instantiateItem
debe estar rodeada porstartUpdate
/finishUpdate
calls. los detalles están en mi respuesta a una pregunta similar: stackoverflow.com/questions/14035090/…OK, creo que he encontrado una manera de realizar la solicitud b) en mi propia pregunta, así que compartiré para beneficio de los demás. La etiqueta de fragmentos dentro de un ViewPager está en el formulario
"android:switcher:VIEWPAGER_ID:INDEX"
, dondeVIEWPAGER_ID
está elR.id.viewpager
diseño en XML, e INDEX es la posición en el visor. Entonces, si se conoce la posición (por ejemplo, 0), puedo realizar enupdateFragments()
:No tengo idea si esta es una forma válida de hacerlo, pero lo hará hasta que se sugiera algo mejor.
fuente
makeFragmentName
utilizado para generar la etiqueta que podría usar en su lugar para un enfoque un poco menos hacky:HomeListFragment fragment = (HomeListFragment) getSupportFragmentManager().findFragmentByTag(FragmentPagerAdapter.makeFragmentName(R.id.viewpager, 0));
makeFragmentName
es unprivate static
método, por lo que no puede acceder a él.Si me pregunta, la segunda solución en la página a continuación, hacer un seguimiento de todas las páginas de fragmentos "activos", es mejor: http://tamsler.blogspot.nl/2011/11/android-viewpager-and-fragments-part -ii.html
La respuesta de Barkside es demasiado hacky para mí.
realiza un seguimiento de todas las páginas de fragmentos "activos". En este caso, realiza un seguimiento de las páginas de fragmentos en el FragmentStatePagerAdapter, que es utilizado por ViewPager.
Para evitar mantener una referencia a las páginas de fragmentos "inactivos", necesitamos implementar el método destroyItem (...) de FragmentStatePagerAdapter:
... y cuando necesita acceder a la página visible actualmente, entonces llama:
... donde el método getFragment (int) de MyAdapter se ve así:
"
fuente
Bien, después de probar el método de @barkside anterior, no pude hacer que funcione con mi aplicación. Entonces recordé que la aplicación IOSched2012 también usa un
viewpager
, y ahí es donde encontré mi solución. No utiliza ninguna ID o etiqueta de fragmento, ya que no se almacenan deviewpager
manera fácilmente accesible.Aquí están las partes importantes de las aplicaciones IOSched HomeActivity. Presta especial atención al comentario , ya que ahí está la clave .:
Y almacene instancias suyas de
Fragments
laFragmentPagerAdapter
misma manera:Además, recuerde proteger sus
Fragment
llamadas así:fuente
getItem()
no se llama después de que el padre se recrea debido a un cambio en el ciclo de vida. Ver stackoverflow.com/a/24662049/236743 . En el ejemplo, esto está parcialmente protegido contra un fragmento, pero no para los otros dosPuede copiar
FragmentPagerAdapter
y modificar algún código fuente, agregargetTag()
métodopor ejemplo
luego extiéndalo, anule estos métodos abstractos, no tenga que temer el cambio de Android Group
FragmentPageAdapter
código fuente en el futurofuente
También funciona sin problemas:
en algún lugar del diseño del fragmento de página:
en el fragmento onCreateView ():
y método para devolver Fragment de ViewPager, si existe:
fuente
Alternativamente, puede anular el
setPrimaryItem
método de estaFragmentPagerAdapter
manera:fuente
Quiero dar mi enfoque en caso de que pueda ayudar a alguien más:
Este es mi adaptador de buscapersonas:
En mi actividad tengo:
Luego, para obtener el fragmento actual, lo que hago es:
fuente
Esta es mi solución ya que no necesito hacer un seguimiento de mis pestañas y necesito actualizarlas todas de todos modos.
fuente