La respuesta principal se basa en un nombre generado por el marco. Si eso cambia, ya no funcionará.
¿Qué pasa con esta solución, primordial instantiateItem()
y destroyItem()
de su Fragment(State)PagerAdapter
:
public class MyPagerAdapter extends FragmentStatePagerAdapter {
SparseArray<Fragment> registeredFragments = new SparseArray<Fragment>();
public MyPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public int getCount() {
return ...;
}
@Override
public Fragment getItem(int position) {
return MyFragment.newInstance(...);
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
Fragment fragment = (Fragment) super.instantiateItem(container, position);
registeredFragments.put(position, fragment);
return fragment;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
registeredFragments.remove(position);
super.destroyItem(container, position, object);
}
public Fragment getRegisteredFragment(int position) {
return registeredFragments.get(position);
}
}
Esto parece funcionar para mí cuando se trata de fragmentos que están disponibles. Los fragmentos que aún no se han instanciado, volverán nulos al llamar getRegisteredFragment
. Pero he estado usando esto principalmente para obtener la corriente Fragment
del ViewPager
: adapater.getRegisteredFragment(viewPager.getCurrentItem())
y esto no volverá null
.
No conozco ningún otro inconveniente de esta solución. Si hay alguno, me gustaría saberlo.
Fragment
de unaWeakReference
para garantizar que no impiden un fragmento destruido de ser recogido de basura? Parece que es lo correcto ...MyPagerAdapter
se destruye debido al ciclo de vida (es decir, rotar), noregisterdFragments
se perderá? ¿Tendrá que usar elActivity
/Fragment
usingMyPagerAdapter
para guardarloonSaveInstanceState
y luego deberá actualizarlo con la nuevaFragmentManager
referencia?getItem
no se vuelve a llamar al rotar (para los fragmentos que ya se crearon), ya queFragmentManager
restaura los estados de losFragments
que contiene en el buscapersonas. SiinstantiateItem
se llama cuandoFragment
se restaura cada uno , entonces esta solución es, de hecho, más segura y una prueba más futura que la mía o la respuesta aceptada. Consideraré probar esto yo mismo.Para obtener fragmentos de un ViewPager hay muchas respuestas aquí y en otros hilos / blogs SO relacionados. Todos los que he visto están rotos, y generalmente parecen caer en uno de los dos tipos enumerados a continuación. Hay algunas otras soluciones válidas si solo desea obtener el fragmento actual, como esta otra respuesta en este hilo.
Si está utilizando
FragmentPagerAdapter
ver más abajo. SiFragmentStatePagerAdapter
vale la pena mirar esto . Los índices de captura que no son los actuales en un FragmentStateAdapter no son tan útiles, ya que por su naturaleza, estos se eliminarán por completo y quedarán fuera de la vista / fuera de los límites fuera de la pantalla.LOS CAMINOS INFELICES
Incorrecto: mantenga su propia lista interna de fragmentos, agregada a cuándo
FragmentPagerAdapter.getItem()
se llamaSparseArray
oMap
getItem
solo se llama la primera vez que se desplaza una página (u se obtiene si suViewPager.setOffscreenPageLimit(x)
> 0) en elViewPager
, si el alojamientoActivity
/Fragment
se elimina o se reinicia, el interno seSpaseArray
borrará cuando se vuelva a crear la FragmentPagerActivity personalizada, pero detrás de escena ViewPagers fragmentos internos serán recreados, ygetItem
se NO ser llamados por cualquiera de los índices, por lo que la posibilidad de obtener un fragmento del índice se perderán para siempre. Puede explicar esto guardando y restaurando estas referencias de fragmentos a través deFragmentManager.getFragment()
y,putFragment
pero esto comienza a complicarse en mi humilde opinión.Incorrecto: construya su propia identificación de etiqueta que coincida con la que se usa debajo del capó
FragmentPagerAdapter
y úsela para recuperar los fragmentos de página delFragmentManager
ViewPager
que podría cambiar en cualquier momento o para cualquier versión del sistema operativo.El método que se recrea para esta solución es
Un camino feliz:
ViewPager.instantiateItem()
Un enfoque similar al
getItem()
anterior pero que no rompe el ciclo de vida es que se conecte eninstantiateItem()
lugar degetItem()
como se llamará al primero cada vez que se cree / acceda a ese índice. Ver esta respuestaUN CAMINO FELIZ: construye tu propio
FragmentViewPager
Construya su propia
FragmentViewPager
clase a partir de la fuente de la última lib de soporte y cambie el método utilizado internamente para generar las etiquetas de fragmentos. Puede reemplazarlo con el siguiente. Esto tiene la ventaja de que sabe que la creación de etiquetas nunca cambiará y que no dependerá de una API / método privado, que siempre es peligroso.Luego, como dice el documento, cuando desee obtener un fragmento utilizado para un índice, simplemente llame a algo como este método (que puede poner en la costumbre
FragmentPagerAdapter
o en una subclase) teniendo en cuenta que el resultado puede ser nulo si getItem aún no se ha solicitado esa página, es decir, aún no se ha creado.Esta es una solución simple y resuelve los problemas en las otras dos soluciones que se encuentran en todas partes en la web
fuente
instantiateItem()
que es cuando desea acceder a un fragmento que aún no se ha visitado después de que se haya producido un evento de ciclo de vida y se haya visitado antes del evento de ciclo de vida. Sé una pequeña diferencia, pero es la que condujo a un error sutil en mi programa, por lo tanto, estoy investigando esto.getItemId(pos)
adentroFragmentStatePagerAdapter
Agregue los siguientes métodos a su FragmentPagerAdapter:
getActiveFragment (0) tiene que funcionar.
Aquí está la solución implementada en ViewPager https://gist.github.com/jacek-marchwicki/d6320ba9a910c514424d . Si algo falla, verá un buen registro de bloqueo.
fuente
Otra solución simple:
fuente
setPrimaryItem()
se llama despuésViewPager.OnPageChangeListener#onPageSelected()
no puedo usarlo :-(Sé que esto tiene algunas respuestas, pero tal vez esto ayude a alguien. He usado una solución relativamente simple cuando necesitaba obtener una
Fragment
de miViewPager
. En suActivity
oFragment
sosteniendo elViewPager
, puede usar este código para recorrer cada uno de losFragment
que contiene.Si conoce la posición de su
Fragment
en elViewPager
, simplemente puede llamargetItem(knownPosition)
.Si no conoce la posición de su
Fragment
en elViewPager
, puede hacer que sus hijosFragments
implementen una interfaz con un método comogetUniqueId()
, y lo usen para diferenciarlos. O puede recorrer todoFragments
y verificar el tipo de clase, comoif(viewPagerFragment instanceof FragmentClassYouWant)
!!! EDITAR !!!
He descubierto que
getItem
solo recibe una llamada de aFragmentPagerAdapter
cuando cada unoFragment
debe crearse la primera vez , después de eso, parece queFragments
se reciclan conFragmentManager
. De esta manera, muchas implementaciones deFragmentPagerAdapter
crear nuevosFragment
s engetItem
. Usando mi método anterior, esto significa que crearemos nuevos correosFragment
electrónicos cada vez quegetItem
se llama a medida que avanzamos por todos los elementos delFragmentPagerAdapter
. Debido a esto, he encontrado un mejor enfoque, usando elFragmentManager
para obtener cada unoFragment
(usando la respuesta aceptada). Esta es una solución más completa y me ha funcionado bien.Y necesitarás este método.
fuente
ViewPager
mismo establece esas etiquetas. Esta solución es frágil porque se basa en conocer la convención de nomenclatura "oculta" deViewPager
. La respuesta de Streets of Boston es una solución mucho más completa, que ahora uso en mi proyecto (en lugar de este enfoque).Para mi caso, ninguna de las soluciones anteriores funcionó.
Sin embargo, dado que estoy usando el Administrador de fragmentos secundarios en un fragmento, se utilizó lo siguiente:
Fragment f = getChildFragmentManager().getFragments().get(viewPager.getCurrentItem());
Esto solo funcionará si sus fragmentos en el Administrador corresponden al elemento del visor.
fuente
fuente
Lo manejé primero haciendo una lista de todos los fragmentos (
List<Fragment> fragments;
) que iba a usar y luego los agregué al buscapersonas para que sea más fácil manejar el fragmento que se ve actualmente.Entonces:
entonces esto se puede llamar:
entonces podría tirarlo en una declaración if que solo se ejecutaría si estuviera en el fragmento correcto
pero ese es solo mi enfoque de pirateo y corte, pero funcionó para mí, lo uso hacer cambios relevantes a mi fragmento actualmente mostrado cuando se presiona el botón Atrás.
fuente
Esto se basa en la respuesta de Steven anterior. Esto devolverá la instancia real del fragmento que ya está adjunto a la actividad principal.
fuente
No pude encontrar una manera simple y limpia de hacer esto. Sin embargo, el widget ViewPager es solo otro ViewGroup, que aloja sus fragmentos. ViewPager tiene estos fragmentos como elementos secundarios inmediatos. Por lo tanto, puede iterar sobre ellos (usando .getChildCount () y .getChildAt ()), y ver si la instancia de fragmento que está buscando está cargada actualmente en ViewPager y obtener una referencia. Por ejemplo, podría usar algún campo de ID único estático para distinguir los fragmentos.
Tenga en cuenta que ViewPager puede no haber cargado el fragmento que está buscando, ya que es un contenedor de virtualización como ListView.
fuente
FragmentPagerAdapter es la fábrica de los fragmentos. Para encontrar un fragmento basado en su posición si todavía está en la memoria, use esto:
Código de muestra para v4 support api.
fuente
No necesita llamar ni ningún
getItem()
otro método en una etapa posterior para obtener la referencia de unFragment
host alojado dentroViewPager
. Si desea actualizar algunos datos dentroFragment
, utilice este enfoque: ¿ Actualizar ViewPager dinámicamente?La clave es establecer nuevos datos dentro
Adaper
y llamar, lonotifyDataSetChanged()
que a su vez lo llamarágetItemPosition()
, pasando una referencia de ustedFragment
y dándole la oportunidad de actualizarlo. Todas las otras formas requieren que mantengas referencia a ti mismo o algún otro truco que no es una buena solución.fuente
getItemPosition()
Es un método en su adaptador. No lo llamarás directamente. Tiene una referencia de su adaptador, por lo que debe llamar, loadapter.notifyDataSetChanged()
que a su vez llamarágetItemPosition()
a su adaptador pasando la referencia de suFragment
s. Puede ver una implementación completa en acción aquí stackoverflow.com/questions/19891828/…Fragment
pero la forma de obtener una referencia es debatible. Otras soluciones obtienen referencia alFragmentManager
usar una cadena similar"android:switcher:"+id
o al volverPOSITION_NONE
degetItemosition()
causar que todos los fragmentos se vuelvan a crear.Debe extenderse
FragmentPagerAdapter
a su clase de adaptador ViewPager.Si usa,
FragmentStatePagerAdapter
entonces no podrá encontrar suFragment
por suID
Cómo usar este método: -
fuente
Hola, he respondido esta pregunta aquí . Básicamente, debes anular
Método de FragmentStatePagerAdapter.
fuente
La mejor solución es usar la extensión que creamos en CodePath llamada SmartFragmentStatePagerAdapter . Siguiendo esa guía, esto hace que la recuperación de fragmentos y el fragmento seleccionado actualmente de un ViewPager sea significativamente más fácil. También hace un mejor trabajo al administrar la memoria de los fragmentos incrustados dentro del adaptador.
fuente
La forma más fácil y concisa. Si todos sus fragmentos
ViewPager
son de diferentes clases, puede recuperarlos y distinguirlos de la siguiente manera:fuente
Implementé esto fácilmente con un enfoque un poco diferente.
Mi método FragmentAdapter.getItem personalizado no devolvió MyFragment () nuevo, sino la instancia de MyFragment que se creó en el constructor FragmentAdapter.
En mi actividad, obtuve el fragmento del adaptador, verifico si es una instancia del Fragmento necesario, luego lanzo y uso los métodos necesarios.
fuente
Crear ID de recurso entero en /values/integers.xml
Luego, en la función PagerAdapter getItem:
Luego, en la actividad, escriba esta función para obtener una referencia de fragmento:
Obtenga la referencia del fragmento llamando a la función anterior y luego transmítala a su fragmento personalizado:
fuente
Manera fácil de iterar sobre fragmentos en el administrador de fragmentos. Busque el visor, que tiene un argumento de posición de sección, colocado en un marcador de posición estático público newInstance (int sectionNumber) .
fuente
En fragmento
En FragmentoActividad
fuente
en TabLayout hay varias pestañas para Fragment. puede encontrar el fragmento por etiqueta utilizando el índice del fragmento.
Por ej. el índice para Fragment1 es 0, por lo que, en el
findFragmentByTag()
método, pase la etiqueta para Viewpager. Después de usar fragmentTransaction, puede agregar y reemplazar el fragmento.String tag = "android:switcher:" + R.id.viewPager + ":" + 0; Fragment1 f = (Fragment1) getSupportFragmentManager().findFragmentByTag(tag);
fuente
Ok para el adaptador
FragmentStatePagerAdapter
, financio una solución:en tu FragmentActivity:
y cree un método en su clase FragmentActivity: para que ese método le dé acceso a su Fragment, solo necesita darle la posición del fragmento que desea:
en su adaptador:
fuente
index
es el lugar del fragmento en el adaptador, como agregófragment1
primero, así quefragment1
pase de nuevoindex
como 0 y así sucesivamente para descansarfuente