Recuperar un fragmento de un ViewPager


248

Estoy usando un ViewPagerjunto con un FragmentStatePagerAdapterpara alojar tres fragmentos diferentes:

  • [Fragmento1]
  • [Fragmento2]
  • [Fragmento3]

Cuando quiero llegar Fragment1desde el ViewPageren el FragmentActivity.

¿Cuál es el problema y cómo lo soluciono?

Respuestas:


504

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 Fragmentdel 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.


41
Esta es la mejor solución que se me ocurre también. La única sugerencia sería para envolver tal vez el Fragmentde una WeakReferencepara garantizar que no impiden un fragmento destruido de ser recogido de basura? Parece que es lo correcto ...
Alex Lockwood

77
¿Qué sucede cuando MyPagerAdapterse destruye debido al ciclo de vida (es decir, rotar), no registerdFragmentsse perderá? ¿Tendrá que usar el Activity/ Fragmentusing MyPagerAdapterpara guardarlo onSaveInstanceStatey luego deberá actualizarlo con la nueva FragmentManagerreferencia?
Steven Byle

10
Si no me equivoco (y debe verificar esto), no se llama al método getItem, como ya sabe, pero se llama al método instantiateItem para cada Fragmento que el marco está restaurando después de una rotación.
Streets Of Boston

66
Sí, he verificado que getItemno se vuelve a llamar al rotar (para los fragmentos que ya se crearon), ya que FragmentManagerrestaura los estados de los Fragmentsque contiene en el buscapersonas. Si instantiateItemse llama cuando Fragmentse 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.
Steven Byle

66
@Dori no lo rompo. Mi solución no está utilizando el resultado de la llamada 'getItem ()'. En cambio, está utilizando el resultado almacenado de la llamada 'instantiateItem ()'. Y el ciclo de vida del fragmento no se rompe, porque el fragmento almacenado se eliminará de la matriz dispersa en la llamada 'destroyItem ()'.
Streets Of Boston

85

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 FragmentPagerAdapterver más abajo. Si FragmentStatePagerAdaptervale 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 llama

  • Usualmente usando un SparseArrayoMap
  • Ninguno de los muchos ejemplos que he visto explica los eventos del ciclo de vida, por lo que esta solución es frágil. Como getItemsolo se llama la primera vez que se desplaza una página (u se obtiene si su ViewPager.setOffscreenPageLimit(x)> 0) en el ViewPager, si el alojamiento Activity/ Fragmentse elimina o se reinicia, el interno se SpaseArrayborrará cuando se vuelva a crear la FragmentPagerActivity personalizada, pero detrás de escena ViewPagers fragmentos internos serán recreados, y getItemse 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 de FragmentManager.getFragment()y, putFragmentpero 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

  • Esto es mejor en la medida en que hace frente al problema de las referencias de fragmentos perdidos en la primera solución de matriz interna, pero como se señala correctamente en las respuestas anteriores y en otras partes de la red, se siente extraño ya que es un método privado interno ViewPagerque 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

private static String makeFragmentName(int viewId, long id) {
    return "android:switcher:" + viewId + ":" + id;
}

Un camino feliz: ViewPager.instantiateItem()

Un enfoque similar al getItem()anterior pero que no rompe el ciclo de vida es que se conecte en instantiateItem()lugar de getItem()como se llamará al primero cada vez que se cree / acceda a ese índice. Ver esta respuesta

UN CAMINO FELIZ: construye tu propio FragmentViewPager

Construya su propia FragmentViewPagerclase 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.

/**
 * @param containerViewId the ViewPager this adapter is being supplied to
 * @param id pass in getItemId(position) as this is whats used internally in this class
 * @return the tag used for this pages fragment
 */
public static String makeFragmentName(int containerViewId, long id) {
    return "android:switcher:" + containerViewId + ":" + id;
}

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 FragmentPagerAdaptero 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.

/**
 * @return may return null if the fragment has not been instantiated yet for that position - this depends on if the fragment has been viewed
 * yet OR is a sibling covered by {@link android.support.v4.view.ViewPager#setOffscreenPageLimit(int)}. Can use this to call methods on
 * the current positions fragment.
 */
public @Nullable Fragment getFragmentForPosition(int position)
{
    String tag = makeFragmentName(mViewPager.getId(), getItemId(position));
    Fragment fragment = getSupportFragmentManager().findFragmentByTag(tag);
    return fragment;
}

Esta es una solución simple y resuelve los problemas en las otras dos soluciones que se encuentran en todas partes en la web


66
Esto funcionará, pero requiere copiar la clase ViewPager en su propio código fuente. Confiar en el 'instantiateItem ()' y 'destroyItem ()' del adaptador de buscapersonas de ViewPager funcionará y respetará los ciclos de vida de los fragmentos (estos 2 métodos también se invocan cuando se crean fragmentos a partir de un estado de instancia guardado). Tiene razón, que confiar en que se llame a 'getItem ()' no es una buena idea y usar API privadas tampoco lo es.
Calles de Boston

+1 acepto que también es una solución y he editado anteriormente. La única diferencia es que lo anterior funciona en un caso de uso más, 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.
Dori

Si setOffscreenPageLimit = 1 (predeterminado), FragmentStatePageAdapter comenzará a intercambiar fragmentos dentro y fuera de la memoria a medida que se accede a las páginas vistas. Mediante una llamada a getItem (), se creará una nueva instancia de páginas / fragmentos revisados. Tras dicha revisión, ¿hay alguna forma de indicarle al sistema que reanude las instancias creadas previamente, en lugar de crear una nueva?
carl

si está fuera del límite de la página, tendrá que crear uno nuevo, pero pasando el estado guardado. Si desea mantener los viejos alrededor, entonces podría aumentar el límite de la página
Dori

@Dori no hay getItemId(pos)adentroFragmentStatePagerAdapter
Jemshit Iskenderov

70

Agregue los siguientes métodos a su FragmentPagerAdapter:

public Fragment getActiveFragment(ViewPager container, int position) {
String name = makeFragmentName(container.getId(), position);
return  mFragmentManager.findFragmentByTag(name);
}

private static String makeFragmentName(int viewId, int index) {
    return "android:switcher:" + viewId + ":" + index;
}

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.


Muchas gracias:) . A través de él lo soplé de otra manera que utilizo un controlador para publicar el fragmento. Esto no es muy adecuado, pero finalmente resolvió el problema. Por cierto, eres agradable :)
Qun Qin

12
Estaba usando este método, pero creo que dejó de funcionar cuando me mudé a API 17 (?). Recomendaría otro método, y preferiría que Google simplemente publicara una API para recuperar un Fragmento de un ViewPager, dada su posición.
gcl1

Tengo un problema con llamar al segundo fragmento, el método crea uno nuevo
Vasil Valchev

2
Dado que alguna versión de API, el método makeFragmentName se cambió a String static privado makeFragmentName (int viewId, long id) {return "android: switcher:" + viewId + ":" + id; } así que el método getActiveFragment ahora debería tener este aspecto (use getItemId en lugar de la posición para el segundo argumento) public Fragment getActiveFragment (ViewPager container, int position) {String name = makeFragmentName (container.getId (), getItemId (position)); return mFragmentManager.findFragmentByTag (nombre); }
Eugene Popovich

1
Realmente funciona, pero es realmente peligroso porque se transmite en la implementación interna del visor de búsqueda y si Google cambia la implementación (y pueden) sucederán cosas malas. Realmente espero que Goole lo ponga a disposición para obtener el fragmento en vivo
shem

38

Otra solución simple:

    public class MyPagerAdapter extends FragmentPagerAdapter {
        private Fragment mCurrentFragment;

        public Fragment getCurrentFragment() {
            return mCurrentFragment;
        }
//...    
        @Override
        public void setPrimaryItem(ViewGroup container, int position, Object object) {
            if (getCurrentFragment() != object) {
                mCurrentFragment = ((Fragment) object);
            }
            super.setPrimaryItem(container, position, object);
        }
    }

1
Esto parece perfecto para mis necesidades actuales de fragmentos.
danny117

Si todo lo que necesita hacer es obtener el Fragmento seleccionado actualmente, esto es todo lo que necesita: el método setPrimaryItem se establece en adjuntar y también en cada actualización del conjunto interno del Fragmento como elemento actual.
Graeme

1
Esto suena como una buena solución, pero como setPrimaryItem()se llama después ViewPager.OnPageChangeListener#onPageSelected() no puedo usarlo :-(
hardysim

21

Sé que esto tiene algunas respuestas, pero tal vez esto ayude a alguien. He usado una solución relativamente simple cuando necesitaba obtener una Fragmentde mi ViewPager. En su Activityo Fragmentsosteniendo el ViewPager, puede usar este código para recorrer cada uno de los Fragmentque contiene.

FragmentPagerAdapter fragmentPagerAdapter = (FragmentPagerAdapter) mViewPager.getAdapter();
for(int i = 0; i < fragmentPagerAdapter.getCount(); i++) {
    Fragment viewPagerFragment = fragmentPagerAdapter.getItem(i);
    if(viewPagerFragment != null) {
        // Do something with your Fragment
        // Check viewPagerFragment.isResumed() if you intend on interacting with any views.
    }
}
  • Si conoce la posición de su Fragmenten el ViewPager, simplemente puede llamar getItem(knownPosition).

  • Si no conoce la posición de su Fragmenten el ViewPager, puede hacer que sus hijos Fragmentsimplementen una interfaz con un método como getUniqueId(), y lo usen para diferenciarlos. O puede recorrer todo Fragmentsy verificar el tipo de clase, comoif(viewPagerFragment instanceof FragmentClassYouWant)

!!! EDITAR !!!

He descubierto que getItemsolo recibe una llamada de a FragmentPagerAdaptercuando cada uno Fragmentdebe crearse la primera vez , después de eso, parece que Fragmentsse reciclan con FragmentManager. De esta manera, muchas implementaciones de FragmentPagerAdaptercrear nuevos Fragment s en getItem. Usando mi método anterior, esto significa que crearemos nuevos correos Fragmentelectrónicos cada vez que getItemse llama a medida que avanzamos por todos los elementos del FragmentPagerAdapter. Debido a esto, he encontrado un mejor enfoque, usando el FragmentManagerpara obtener cada uno Fragment(usando la respuesta aceptada). Esta es una solución más completa y me ha funcionado bien.

FragmentPagerAdapter fragmentPagerAdapter = (FragmentPagerAdapter) mViewPager.getAdapter();
for(int i = 0; i < fragmentPagerAdapter.getCount(); i++) {
    String name = makeFragmentName(mViewPager.getId(), i);
    Fragment viewPagerFragment = getChildFragmentManager().findFragmentByTag(name);
    // OR Fragment viewPagerFragment = getFragmentManager().findFragmentByTag(name);
    if(viewPagerFragment != null) {

        // Do something with your Fragment
        if (viewPagerFragment.isResumed()) {
            // Interact with any views/data that must be alive
        }
        else {
            // Flag something for update later, when this viewPagerFragment
            // returns to onResume
        }
    }
}

Y necesitarás este método.

private static String makeFragmentName(int viewId, int position) {
    return "android:switcher:" + viewId + ":" + position;
}

1
Simplemente encuentra FragmentByTag (), pero ¿dónde podríamos configurar el TAG con fragmento?
VinceStyling

@vince El ViewPagermismo establece esas etiquetas. Esta solución es frágil porque se basa en conocer la convención de nomenclatura "oculta" de ViewPager. 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).
Steven Byle

¡Esto funciona muy bien! Pero eliminé el condicional "if (viewPagerFragment.isResumed ())" porque necesito actualizar mis páginas ListFragment que están fuera de la pantalla. Luego, cuando el usuario vuelve a la página ListFragment, todo se actualiza con los nuevos datos.
JDJ

10

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.


Esta es la respuesta perfecta para obtener fragmentos antiguos del localizador de vistas cuando se recrea la actividad o el fragmento.
Smeet

7

Para obtener el fragmento Visible actual de ViewPager . Estoy usando esta simple declaración y está funcionando bien.

      public Fragment getFragmentFromViewpager()  
      {
         return ((Fragment) (mAdapter.instantiateItem(mViewPager, mViewPager.getCurrentItem())));
      }

3

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:

@Override
onCreate(){
    //initialise the list of fragments
    fragments = new Vector<Fragment>();

    //fill up the list with out fragments
    fragments.add(Fragment.instantiate(this, MainFragment.class.getName()));
    fragments.add(Fragment.instantiate(this, MenuFragment.class.getName()));
    fragments.add(Fragment.instantiate(this, StoresFragment.class.getName()));
    fragments.add(Fragment.instantiate(this, AboutFragment.class.getName()));
    fragments.add(Fragment.instantiate(this, ContactFragment.class.getName()));


    //Set up the pager
    pager = (ViewPager)findViewById(R.id.pager);
    pager.setAdapter(new MyFragmentPagerAdapter(getSupportFragmentManager(), fragments));
    pager.setOffscreenPageLimit(4);
}

entonces esto se puede llamar:

public Fragment getFragment(ViewPager pager){   
    Fragment theFragment = fragments.get(pager.getCurrentItem());
    return theFragment;
}

entonces podría tirarlo en una declaración if que solo se ejecutaría si estuviera en el fragmento correcto

Fragment tempFragment = getFragment();
if(tempFragment == MyFragmentNo2.class){
    MyFragmentNo2 theFrag = (MyFragmentNo2) tempFragment;
    //then you can do whatever with the fragment
    theFrag.costomFunction();
}

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.


1
mejor respuesta para mí
Sonu Kumar

3

Esto se basa en la respuesta de Steven anterior. Esto devolverá la instancia real del fragmento que ya está adjunto a la actividad principal.

FragmentPagerAdapter fragmentPagerAdapter = (FragmentPagerAdapter) mViewPager.getAdapter();
    for(int i = 0; i < fragmentPagerAdapter.getCount(); i++) {

        Fragment viewPagerFragment = (Fragment) mViewPager.getAdapter().instantiateItem(mViewPager, i);
        if(viewPagerFragment != null && viewPagerFragment.isAdded()) {

            if (viewPagerFragment instanceof FragmentOne){
                FragmentOne oneFragment = (FragmentOne) viewPagerFragment;
                if (oneFragment != null){
                    oneFragment.update(); // your custom method
                }
            } else if (viewPagerFragment instanceof FragmentTwo){
                FragmentTwo twoFragment = (FragmentTwo) viewPagerFragment;

                if (twoFragment != null){
                    twoFragment.update(); // your custom method
                }
            }
        }
    }

2

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.


1
Gracias por su respuesta, lo recupero con el adpter.getItem (); Soy un estudiante de primer año en la programación de Android. Realmente te aprecio mucho. Ahora puedo recuperar el ListFragment y quiero agregar footerView, mientras hago esto en mi Actividad, luego el logcat imprime: "java.lang.IllegalStateException: Vista de contenido aún no creada." Sé por qué pero tengo dificultades para tratar con eso.
Qun Qin

1
FragmentActivity tiene el método onAttachFragment (), ¿dosifica este trabajo para ViewPager con contenido de fragmentos?
Vasil Valchev

2

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:

public Fragment findFragmentByPosition(int position) {
    FragmentPagerAdapter fragmentPagerAdapter = getFragmentPagerAdapter();
    return getSupportFragmentManager().findFragmentByTag(
            "android:switcher:" + getViewPager().getId() + ":"
                    + fragmentPagerAdapter.getItemId(position));
}

Código de muestra para v4 support api.


Está volviendo nulo en onresume (). ¿Alguna idea de por qué y cómo arreglarlo?
seema

2

No necesita llamar ni ningúngetItem() otro método en una etapa posterior para obtener la referencia de un Fragmenthost alojado dentro ViewPager. Si desea actualizar algunos datos dentro Fragment, utilice este enfoque: ¿ Actualizar ViewPager dinámicamente?

La clave es establecer nuevos datos dentro Adapery llamar, lo notifyDataSetChanged()que a su vez lo llamará getItemPosition(), pasando una referencia de usted Fragmenty 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.

@Override
public int getItemPosition(Object object) {
    if (object instanceof UpdateableFragment) {
        ((UpdateableFragment) object).update(xyzData);
    }
    //don't return POSITION_NONE, avoid fragment recreation. 
    return super.getItemPosition(object);
}

No entiendo aquí, necesitas una referencia de un Fragmento para usar getItemPosition (), por lo que es mejor que no uses getItemPosition, ¿eh?

getItemPosition()Es un método en su adaptador. No lo llamarás directamente. Tiene una referencia de su adaptador, por lo que debe llamar, lo adapter.notifyDataSetChanged()que a su vez llamará getItemPosition()a su adaptador pasando la referencia de su Fragments. Puede ver una implementación completa en acción aquí stackoverflow.com/questions/19891828/…
M-WaJeEh

Lo he leído y todavía no lo entiendo. Todavía necesitarías una referencia directa a esos fragmentos para hacer llamadas contra ellos, ¿verdad? Lo mencionas como un truco, pero no veo una alternativa; adaptador.getItem (i) obviamente no va a funcionar.

2
Ok, he actualizado mi respuesta para aclarar más. Por supuesto, se necesita una referencia para actualizar, Fragmentpero la forma de obtener una referencia es debatible. Otras soluciones obtienen referencia al FragmentManagerusar una cadena similar "android:switcher:"+ido al volver POSITION_NONEde getItemosition()causar que todos los fragmentos se vuelvan a crear.
M-WaJeEh

Gracias, esto tiene mucho más sentido y coincide con mi experiencia (por lo que es posible que no esté haciendo algo mal, ja).

2

Debe extenderse FragmentPagerAdaptera su clase de adaptador ViewPager.
Si usa, FragmentStatePagerAdapterentonces no podrá encontrar su Fragmentpor suID

public static String makeFragmentName(int viewPagerId, int index) {
  return "android:switcher:" + viewPagerId + ":" + index;
}

Cómo usar este método: -

Fragment mFragment = ((FragmentActivity) getContext()).getSupportFragmentManager().findFragmentByTag(
       AppMethodUtils.makeFragmentName(mViewPager.getId(), i)
);
InterestViewFragment newFragment = (InterestViewFragment) mFragment;

2

Hola, he respondido esta pregunta aquí . Básicamente, debes anular

Objeto público instantiateItem (contenedor ViewGroup, posición int)

Método de FragmentStatePagerAdapter.


1

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.


0

La forma más fácil y concisa. Si todos sus fragmentos ViewPagerson de diferentes clases, puede recuperarlos y distinguirlos de la siguiente manera:

public class MyActivity extends Activity
{

    @Override
    public void onAttachFragment(Fragment fragment) {
        super.onAttachFragment(fragment);
        if (fragment.getClass() == MyFragment.class) {
            mMyFragment = (MyFragment) fragment;
        }
    }

}

Esto también está mal, ya que hay múltiples fragmentos que se adjuntan cuando usa ViewPager. existe el fragmento de página actual, y hay uno a la izquierda y otro a la derecha. Esto permite al usuario deslizarse entre ellos sin tener que inicializarlos solo cuando el usuario los alcanza.
Desarrollador de Android

0

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.


0

Crear ID de recurso entero en /values/integers.xml

<integer name="page1">1</integer>
<integer name="page2">2</integer>
<integer name="page3">3</integer>

Luego, en la función PagerAdapter getItem:

public Fragment getItem(int position) {

        Fragment fragment = null;

        if (position == 0) {
            fragment = FragmentOne.newInstance();
            mViewPager.setTag(R.integer.page1,fragment);

        }
        else if (position == 1) {

            fragment = FragmentTwo.newInstance();
            mViewPager.setTag(R.integer.page2,fragment);

        } else if (position == 2) {

            fragment = FragmentThree.newInstance();
            mViewPager.setTag(R.integer.page3,fragment);

        }

        return fragment;
        }

Luego, en la actividad, escriba esta función para obtener una referencia de fragmento:

private Fragment getFragmentByPosition(int position) {
    Fragment fragment = null;

    switch (position) {
        case 0:
            fragment = (Fragment) mViewPager.getTag(R.integer.page1);
            break;

        case 1:

            fragment = (Fragment) mViewPager.getTag(R.integer.page2);
            break;

        case 2:
            fragment = (Fragment) mViewPager.getTag(R.integer.page3);
            break;
            }

            return fragment;
    }

Obtenga la referencia del fragmento llamando a la función anterior y luego transmítala a su fragmento personalizado:

Fragment fragment = getFragmentByPosition(position);

        if (fragment != null) {
                    FragmentOne fragmentOne = (FragmentOne) fragment;
                    }

0

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) .

public PlaceholderFragment getFragmentByPosition(Integer pos){
    for(Fragment f:getChildFragmentManager().getFragments()){
        if(f.getId()==R.id.viewpager && f.getArguments().getInt("SECTNUM") - 1 == pos) {
            return (PlaceholderFragment) f;
        }
    }
    return null;
}

0

En fragmento

public int getArgument(){
   return mPage;
{
public void update(){

}

En FragmentoActividad

List<Fragment> fragments = getSupportFragmentManager().getFragments();
for(Fragment f:fragments){
    if((f instanceof PageFragment)&&(!f.isDetached())){
          PageFragment pf = (PageFragment)f;   
          if(pf.getArgument()==pager.getCurrentItem())pf.update();
    }
}

0

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);


-1

Ok para el adaptador FragmentStatePagerAdapter, financio una solución:

en tu FragmentActivity:

ActionBar mActionBar = getSupportActionBar(); 
mActionBar.addTab(mActionBar.newTab().setText("TAB1").setTabListener(this).setTag(Fragment.instantiate(this, MyFragment1.class.getName())));
mActionBar.addTab(mActionBar.newTab().setText("TAB2").setTabListener(this).setTag(Fragment.instantiate(this, MyFragment2.class.getName())));
mActionBar.addTab(mActionBar.newTab().setText("TAB3").setTabListener(this).setTag(Fragment.instantiate(this, MyFragment3.class.getName())));

viewPager = (STViewPager) super.findViewById(R.id.viewpager);
mPagerAdapter = new MyPagerAdapter(getSupportFragmentManager(), mActionBar);
viewPager.setAdapter(this.mPagerAdapter);

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:

public Fragment getActiveFragment(int position) {
String name = MyPagerAdapter.makeFragmentName(position);
return getSupportFragmentManager().findFragmentByTag(name);
}

en su adaptador:

public class MyPagerAdapter extends FragmentStatePagerAdapter {

private final ActionBar actionBar;
private final FragmentManager fragmentManager;

public MyPagerAdapter(FragmentManager fragmentManager, com.actionbarsherlock.app.ActionBarActionBar mActionBar) {super(fragmentManager);
this.actionBar = mActionBar;
this.fragmentManager = fragmentManager;
}

@Override
public Fragment getItem(int position) {
getSupportFragmentManager().beginTransaction().add(mTchatDetailsFragment, makeFragmentName(position)).commit();
return (Fragment)this.actionBar.getTabAt(position);
}

@Override
public int getCount() {
return this.actionBar.getTabCount();
}

@Override
public CharSequence getPageTitle(int position) {
return this.actionBar.getTabAt(position).getText();
}

private static String makeFragmentName(int viewId, int index) {
return "android:fragment:" + index;
}

}

-1
Fragment yourFragment = yourviewpageradapter.getItem(int index);

indexes el lugar del fragmento en el adaptador, como agregó fragment1primero, así que fragment1pase de nuevo indexcomo 0 y así sucesivamente para descansar

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.