Join FlipAndroid.COM Telegram Group: https://t.me/joinchat/F_aqThGkhwcLzmI49vKAiw


Fragmentos: Eliminar todos los fragmentos en una vista

El escenario que me enfrento, es en mi aplicación tengo un solo panel y diseño de estilo de panel doble . En lugar de manejar individualmente cada operación de navegación única posible entre las pantallas, para cada estilo diferente de diseño, estoy usando una función que establece el diseño correctamente cuando se le da la pantalla deseada.

Es básicamente una instrucción switch para cada pantalla de la aplicación, con una sentencia switch anidado en cada pantalla para manejar cada estilo de diseño. Esto es lo que estoy hablando en código:

 protected void setupScreen() { switch(currentScreen) { case SCREEN_ONE: switch(currentLayout) { case SINGLE_PANE: // Perform actions to setup the screen break; case DUAL_PANE: // Perform actions to setup the screen break; } break; case SCREEN_TWO: switch(currentLayout) { case SINGLE_PANE: // Perform actions to setup the screen break; case DUAL_PANE: // Perform actions to setup the screen break; } break // ... etc .... } } 

En la sección donde quiero realizar las acciones para configurar la pantalla , ésta consta de las siguientes tres operaciones básicas:

 // Create the fragments if necessary if (screenFragment == null) { screenFragment = new myFragment(); } // Remove the existing fragments from the layout views // HOW??? // Add the fragments for this screen to the view getSupportFragmentManager().beginTransaction().add(pane1.getId(), myFragment, "myFragment").commit(); 

Como puede ver, lo que estoy luchando con es cómo hacer el segundo paso. ¿Cómo se eliminan todos los Fragment de una View determinada sin saber exactamente cuáles son los que desea eliminar? El más cercano que he encontrado es FragmentTransaction.replace() que hace esto con éxito para cada caso, pero cuando resulta que está reemplazando un Fragment con el mismo fragmento. En este caso, no quita todo, después agrega (como la documentación sugiere), apenas parece quitar. ¿Es esto un problema con el uso de las bibliotecas de compatibilidad o no es la forma FragmentTransaction.replace() debe ser utilizado?

En cualquier caso, ¿cómo debo hacer esto? ¿Tengo que codificar una función removeAllFragments() para ir a través de cada fragmento y separarlo o hay una manera de hacer la primera mitad de lo que el 'dos ​​en uno' FragmentTransaction.replace() función pretende hacer?

  • NullPointerException: Intenta invocar el método virtual 'int java.util.ArrayList.size ()' en una referencia de objeto nulo
  • Android - addToBackStack () no funciona?
  • ViewPager con indicador sin la biblioteca de soporte de Android
  • Coordinador
  • ¿Por qué usar Fragmentos?
  • ViewFlipper vs Fragments
  • AndroidRuntimeException: requestFeature () debe ser llamado antes de agregar contenido
  • Convertir la actividad en fragmento
  • 5 Solutions collect form web for “Fragmentos: Eliminar todos los fragmentos en una vista”

    El mecanismo típico es utilizar FragmentManager.findFragmentByTag() . Utiliza esto y agrega etiquetas a tus fragmentos (o la alternativa para id's). De esta manera puede determinar qué fragmentos se están administrando actualmente. Luego, una vez que tenga un identificador a un fragmento presente (findFragmentByTag devuelve no nulo), puede utilizar FragmentManager.beginTransaction() para iniciar un FrgamentTransaction y eliminar / agregar los fragmentos necesarios. Trabajar de esta manera le permitirá evitar el proceso de "re-adición" del fragmento que desea conservar.

    Lo que probablemente haría es tener un código así: (código psuedo de advertencia)

     Fragment pane1 = FragmentManager.findFragmentByTag("myFragmentPane1"); Fragment pane2 = FragmentManager.findFragmentByTag("myFragmentPane2"); setupScreen(pane1, pane2); 

    También debe considerar subclases de su clase en lugar de tener "todo en una clase". Usted tiene un caso bastante obvio de Martin Fowler's Replace Conditional with Subclass . De lo contrario, me temo que esto va a ser increíblemente difícil de manejar cuando se agrega otra pantalla.

    Ninguna de las otras respuestas realmente funcionaban para mí. Esto es lo que hice:

     List<Fragment> al = getSupportFragmentManager().getFragments(); if (al == null) { // code that handles no existing fragments return; } for (Fragment frag : al) { // To save any of the fragments, add this check. // A tag can be added as a third parameter to the fragment when you commit it if (frag == null || frag.getTag().equals("<tag-name>")) { continue; } getSupportFragmentManager().beginTransaction().remove(frag).commit(); } 

    O, si se ve obligado a usarlo (pero no se recomienda):

     .commitAllowingStateLoss(); 

    Además, si está quitando todos los fragmentos de la vista varias veces, podría considerar verificar si el frag actual es null o isDetached() o isRemoving() o puede obtener NullPointerExceptions .

    Actualización : La documentación para getSupportFragmentManger().getFragments() aparentemente está oculta ahora, pero todavía funciona muy bien en mi código. Aquí está la captura de pantalla de la documentación:

    Introduzca aquí la descripción de la imagen

    Dicho esto, ya que está oculto, ya no quieren este método utilizado, así que ver mi actualización a continuación.

    Actualización 8-4-15 : Si no está utilizando la biblioteca de soporte para fragmentos, no hay desafortunadamente getFragments() disponible, pero todavía hay un par, más inconveniente, las opciones.

    1. Dé a cada fragment una tag o un id en la creación, e iterate a través de ellos para procesar cada fragment según lo deseado.
    2. Cree un listener utilizando onAttachListener para que cada vez que se onAttachListener un nuevo fragment a la activity , puede almacenar ese fragment y, a continuación, iterar a través de esa estructura de datos para procesar cada fragment según se desee.

    Cuando no use getSupportFragmentManager() , para procesar una transacción necesitará usar getFragmentManager() lugar.

    Si utiliza android.support.v4.app.Fragment puede hacer esto:

     List<Fragment> fragments = getSupportFragmentManager().getFragments(); if (fragments != null) { for (Fragment fragment : fragments) { getSupportFragmentManager().beginTransaction().remove(fragment).commit(); } } 

    Resulta que FragmentTransaction.replace() es la operación correcta y debería funcionar correctamente. Sólo no funciona cuando se utiliza ActionBarSherlock y SherlockFragmentActivity por lo que sólo puedo asumir que es un error en esta biblioteca de compatibilidad.

    He confirmado esto mediante el uso del código siguiente para implementar el comportamiento deseado a través de Android en API11 +, la biblioteca de compatibilidad de Android y ActionBarSherlock. Sólo se rompe en el último caso.

     package com.test.test; import com.actionbarsherlock.app.SherlockFragmentActivity; import android.os.Bundle; import android.content.Context; import android.graphics.Color; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentActivity; import android.view.Gravity; import android.view.LayoutInflater; import android.view.Menu; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.Button; import android.widget.FrameLayout; import android.widget.LinearLayout; import android.widget.LinearLayout.LayoutParams; import android.widget.TextView; public class MainActivity extends SherlockFragmentActivity { // Consistent fragment instance myFragment myFrag = null; // Views FrameLayout fl = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); LinearLayout ll = new LinearLayout(this); ll.setOrientation(LinearLayout.VERTICAL); Button b = new Button(this); b.setText("Repeat"); b.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // Reattach the same fragment getSupportFragmentManager().beginTransaction().replace(fl.getId(), myFrag).commit(); } }); fl = new FrameLayout(this); fl.setId(200); fl.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); myFrag = new myFragment(); getSupportFragmentManager().beginTransaction().add(fl.getId(), myFrag).commit(); ll.addView(b); ll.addView(fl); setContentView(ll); } public static class myFragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { TextView tv = new TextView(getActivity()); tv.setText("My fragment"); tv.setGravity(Gravity.CENTER); tv.setBackgroundColor(Color.RED); return tv; } } } 

    Esto es más o menos cómo he manejado esto. Haga que todos sus fragmentos implementen una interfaz como:

     public interface NamedFragment{ public FragmentName getFragmentName(); } 

    Haz un enum correspondiente a tus fragmentos:

     public enum FragmentName{ SOME_FRAGMENT, SOME_OTHER_FRAGMENT; } 

    Entonces en su fragmento de la actividad de conmutación:

     // Get the manager and transaction separately so you can use both: FragmentManager fragmentManager = getSupportFragmentManager(); FragmentTransaction ft = fragmentManager.beginTransaction(); // Get a reference to the fragment(s) currently in the container(s) Fragment currentFragment = fragmentManager.findFragmentById(position); FragmentName cFragmentName = ((NamedFragment) currentFragment).getFragmentName(); Fragment nextFragment = Fragment.instantiate(this, some_new_fragment_string); FragmentName nFragmentName = ((NamedFragment) nextFragment).getFragmentName(); // Compare the "names" if(cFragmentName != nFragmentName){ ft.replace(position, nextFragment); } 

    Usted tendrá que cambiar las cosas un poco para adaptarse a sus datos.

    FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.