El escenario me estoy enfrentando, es en mi aplicación tengo un único panel y de doble panel estilo de diseño. En lugar de individualmente manejo de cada uno de manejo de la navegación entre las pantallas, diferente para cada estilo de diseño, estoy usando una función que establece el diseño correctamente cuando se administra la pantalla deseada.

Es básicamente un switch declaración para cada pantalla de la aplicación, con un anidada switch declaración en cada pantalla para manejar cada estilo de diseño. Esto es lo que te 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 la instalación de la pantalla, este consta de los siguientes tres operaciones:

//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 se puede ver, lo que yo estoy luchando con es cómo a hacer el segundo paso. Cómo ¿eliminar todos los Fragments de un determinado View sin saber exactamente cuáles son ganas de quitar? El más cercano que he encontrado es FragmentTransaction.replace() que hace con éxito hacer esto para cada caso pero cuando resulta que usted está reemplazando un Fragment con el mismo fragmento. En este caso, no se quitan todas, a continuación, añadir (como sugiere la documentación), apenas se parece a quitar. Esto es un problema con el uso de las bibliotecas de compatibilidad o no es la forma en que FragmentTransaction.replace() se debe usar?

En cualquier caso, ¿cómo debo hacerlo? Tengo el código de un removeAllFragments() función para ir a través de cada fragmento y separe o hay una manera de hacer la primera mitad de lo que el ‘dos en uno’ FragmentTransaction.replace() función de reclamaciones a hacer?

OriginalEl autor B T | 2013-02-08

5 Comentarios

  1. 7

    El mecanismo típico es el uso de FragmentManager.findFragmentByTag() . Utilice este y agregar etiquetas a sus fragmentos (o la alternativa para la identificación). De esta manera usted puede determinar qué fragmentos son gestionados actualmente. Luego, una vez que usted tiene un identificador para un presente fragmento (findFragmentByTag devuelve distinto de null), puede utilizar FragmentManager.beginTransaction() para iniciar un FrgamentTransaction y eliminar /añadir la necesaria fragmentos. Con esta forma de trabajo le permitirá evitar la re-incorporación de’ proceso por el fragmento que desea mantener.

    Lo que probablemente iba a hacer es tener el código así: (advertencia de pseudo código)

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

    Usted debería considerar también la posibilidad de sub-clases de la clase en lugar de tener «todo en uno de la clase’. Usted tiene una bastante obvia caso de Martin Fowler Reemplazar Condicional con la Subclase. De lo contrario, me temo que esto va a ser muy duro para el administrador cuando se agrega otra pantalla.

    +1, suena tonto, pero nunca han pensado en el uso de la Etiqueta para identificar donde el fragmento se coloca, siempre que se utilizan para identificar qué tipo el fragmento es

    OriginalEl autor Nick Campion

  2. 19

    Ninguna de las otras respuestas fueron realmente trabajando 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 usted está obligado a usar (pero no recomendable):

    .commitAllowingStateLoss();

    También, si usted está quitando todos los fragmentos de la vista varias veces, usted podría considerar la posibilidad de comprobar si la actual fragmentación es nulo o isDetached() o isRemoving(), o usted podría conseguir NullPointerExceptions.

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

    Fragmentos: Retire todos los fragmentos en una vista

    Habiendo dicho eso, ya que está oculto, que ya no desea que este método utilizado, así que consulte con mi actualización a continuación.

    Actualización 8-4-15: Si no estás usando el apoyo de la biblioteca de fragmentos, desgraciadamente no hay getFragments() disponible, pero todavía hay un par, más incómodo, opciones.

    1. Dar a cada fragment un tag o id momento de su creación, y recorrer a través de ellos para procesar cada fragment como se desee.
    2. Crear un detector utilizando onAttachListener por lo que cada vez que un nuevo fragment se adjunta a la activity, puede almacenar que fragment, y luego iterar a través de esa estructura de datos para el proceso de cada fragment como se desee.

    Cuando no se utiliza el getSupportFragmentManager(), para procesar una transacción deberá utilizar getFragmentManager() lugar.

    Votada abajo, porque no hay ninguna getFragments() de la API.
    En realidad, no existe; es sólo que ha estado oculto desde esta respuesta fue escrito. Y aún funciona. Intente.
    Esto no es cierto. Se presenta sólo en el apoyo de la biblioteca desde 4.3, sin embargo, es que no se presenta en android.app.FragmentManager. La respuesta está llevando en la dirección equivocada y aplicable sólo para el apoyo de la biblioteca (con menciones sobre el uso de hidden API).
    Oh, no me di cuenta de que estaba hablando con el modo normal de FragmentManager, en lugar de la SupportFragmentManager. Tienes razón; no hay getFragments() para android.app.FragmentManager. Ver mi respuesta actualizada.
    Gracias por darme una razón para la downvote así que podía arreglarlo!

    OriginalEl autor craned

  3. 3

    Si utiliza android.apoyo.v4.app.Fragmento usted puede hacer esto:

    List<Fragment> fragments = getSupportFragmentManager().getFragments();
    if (fragments != null) {
        for (Fragment fragment : fragments) {
            getSupportFragmentManager().beginTransaction().remove(fragment).commit();
        }
    }
    No funciona? se dice que se requiere android.app.Fragment
    usted tiene que usar getFragmentManager() en su caso de uso

    OriginalEl autor bluebeat

  4. 1

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

    Me han confirmado este medio, utilizando el siguiente código 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 la última instancia.

    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;
    }
    }
    }
    +1 Add es realmente diferente de Replace.

    OriginalEl autor B T

  5. 0

    Esto es más o menos cómo he manejado esto. Tiene todos sus fragmentos implementar una interfaz algo como:

    public interface NamedFragment{
    public FragmentName getFragmentName();
    }

    Hacer una enumeración correspondiente a sus fragmentos:

    public enum FragmentName{
    SOME_FRAGMENT,
    SOME_OTHER_FRAGMENT;
    }

    A continuación, en el fragmento de la conmutación de la actividad:

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

    Vas a tener que cambiar las cosas un poco para adaptarse a sus particularidades.

    Mi respuesta tiene sentido si sólo se desea una instancia de una clase determinada en un momento; @Nick tiene sentido si usted necesita identificadores únicos para cada instancia.

    OriginalEl autor anthropomo

Dejar respuesta

Please enter your comment!
Please enter your name here