2012-06-01 13 views
37

Al usar ViewPager con fragmentos, nuestros métodos onPause(), onResume() no se invocan cuando se mueve entre pestañas. ¿Hay alguna manera de que podamos descubrir el fragmento cuando nos estamos haciendo visibles o escondidos?ViewPager con fragmentos - onPause(), onResume()?

Lamentablemente tengo lógica en onResume(), onPause(), como registrarme en servicios de ubicación, que nunca se detienen al cambiar de pestaña porque onPause() nunca se llama hasta que se sale de toda la aplicación.

Gracias

Respuesta

17

El ViewPager viene con la interfaz OnPageChangeListener. Al establecer algunos indicadores para las páginas anteriores y actuales, puede emular este comportamiento.

+0

podría darle un poco más de información? – Darkhogg

+1

Supongo que durante la devolución de llamada OnPageChange(), puede establecer el UserVisiblityHint en true en el nuevo fragmento seleccionado y en false en el fragmento anterior. Luego llamando a sus respectivos métodos on Resume() y onPause(). La sugerencia de visibilidad del usuario debe registrarse en Repetición() para garantizar que la llamada se realiza durante el Cambio de página en lugar del estándar durante la creación del fragmento. ¿Existe una bandera real para recuperar el comportamiento documentado? – 3c71

+0

Lo siento amigo, he estado fuera de la ciudad. Me alegro de que alguien haya venido! – Phix

10

Teniendo en cuenta las soluciones anteriores no son muy claras, aquí es cómo lo resolví gracias a Phix por su pista:

En el OnPageChange() de devolución de llamada:

Fragment old_fragment = getActiveFragment(old_position); 
    Fragment new_fragment = getActiveFragment(new_position); 
    old_f.setUserVisibleHint(false); 
    old_f.onPause(); 
    new_f.setUserVisibleHint(true); 
    new_f.onResume(); 

Luego, en onResume():

if (getUserVisibleHint()) 
     /* resume code */ 

y en onPause():

if (!getUserVisibleHint()) 
     /* pause code */ 

Este es el código getActiveFragment, evitando a buscar eso también:

return fragmentManager.findFragmentByTag("android:switcher:" + viewPagerId + ":" + position); 

NB: El fragmento tiene un método isVisible(), pero no parece ser muy constante, de ahí el uso de UserVisibleHint.

EDITAR: Reemplace el UserVisibleHint por una bandera privada. ¡Trabajó mucho mejor!

+13

Llamar a los métodos del ciclo de vida directamente nunca es una buena solución – Emmanuel

+0

Claro que no es una buena solución, pero no hay otra en el momento para solucionar este "error" o comportamiento del sistema operativo. ¿Por qué los fragmentos tienen onResume() onPause() pero nunca se llama en primer lugar? – 3c71

+4

No es un error del sistema operativo. Esto significa que el 'Fragmento' todavía está en la memoria. 'ViewPager' retendrá en la memoria al menos 2' Fragments' en su naturaleza de paginación. Mira esto [respuesta] (http://stackoverflow.com/a/11650582/2029566) para más detalles. – Emmanuel

2

Solución 1:

definir un SparseArray en sus ViewPagers 'adaptadores, como a continuación. En este conjunto, mantendremos la instancia de fragmentos.

SparseArray<Fragment> registeredFragments = new SparseArray<>(); 

Y OverrideinstantiateItem método de sus adaptadores.

@Override 
public Object instantiateItem(ViewGroup container, int position) { 
    Fragment fragment = (Fragment) super.instantiateItem(container, position); 
    registeredFragments.put(position, fragment); 
    return fragment; 
} 

también OverridedestroyItem método de su ViewPagers

@Override 
public void destroyItem(ViewGroup container, int position, Object object) { 
    registeredFragments.remove(position); 
    super.destroyItem(container, position, object); 
} 

y definir un nuevo método para obtener la instancia de ViewPagerFragments.

public Fragment getRegisteredFragment(int position) { 
    return registeredFragments.get(position); 
} 

Ahora puede implementar su lógica con ViewPager'sOnPageChangeListener. He aquí un ejemplo de cómo se puede implementar de una ViewPager onPageChangeListener:

Definir un entero para mantener la posición actual:

int currentPos; 

yourViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { 
      @Override 
      public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { 
       // Empty method 
      } 

      @Override 
      public void onPageSelected(int position) { 
        // This is paused fragment. 
        final Fragment pausedFragment = yourAdapter.getRegisteredFragment(currentPos); 

        // update current position value 
        currentPos = position; 

        // This is resumed fragment 
        final Fragment resumedFragment = yourAdapter.getRegisteredFragment(currentPos); 
      } 

      @Override 
      public void onPageScrollStateChanged(int state) { 
       // Empty method 
      } 
     }); 

Finalmente, para la restauración de estado de la instancia actualizar su posición actual a mantenerse al día en el que el usuario posición a la izquierda ViewPager

currentPos = yourViewPager.getCurrentItem(); 

Solución 2:

Para otra solución puede encontrar su ViewPagerFragments por Tag. Puede generar su etiqueta con:

@NonNull 
public static String generateViewPagerFragmentTag(int viewPagerId, int position) { 
     final StringBuilder tagBuilder = new StringBuilder(); 
     tagBuilder.append("android:switcher:"); 
     tagBuilder.append(viewPagerId); 
     tagBuilder.append(":"); 
     tagBuilder.append(position); 
     return tagBuilder.toString(); 
    } 

y encontrar su Fragment:

final Fragment yourFragment = getSupportFragmentManager().findFragmentByTag(generateViewPagerFragmentTag(R.id.your_viewpager, currentPos)); 

Edición: hace unos años, mientras que yo estaba buscando una solución para conseguir elemento actual de ViewPager he intentado UserVisibleHint en Fragments y notó que no era confiable. No estoy seguro de si es confiable o no ahora, pero aún así evito usarlo.

0

para dar un poco más de definición de los métodos de savepopulation 's respuesta:

yourPager.setOnPageChangeListener(new GridViewPager.OnPageChangeListener() { 
     @Override 
     public void onPageScrolled(int row, int column, float rowOffset, float columnOffset, int rowOffsetPixels, int columnOffsetPixels) { 

     } 

     @Override 
     public void onPageSelected(int row, int column) { 
      // When on page selected if position is not specific for you 
      // you can find your fragment or you can switch position. 
     } 

     @Override 
     public void onPageScrollStateChanged(int state) { 

     } 
    }); 
2

Usted puede utilizar a continuación el método de Fragment

public void setUserVisibleHint(boolean isVisibleToUser){ 

} 

cuando isVisibleToUser == true, el fragmento se muestra

0

Si u está utilizando la biblioteca de compatibilidad de Android (rev 11), puede utilizar getUserVisibleHint() o anular setUserVisibleHint() para capturar los cambios sean visibles y se esconden. Mira esto post.

@Override 
 
public void setUserVisibleHint(boolean isVisibleToUser) { 
 
    super.setUserVisibleHint(isVisibleToUser); 
 
    if (isVisibleToUser) { 
 
     // do something when visible. 
 
    } 
 
}

Cuestiones relacionadas