Mostrar ocultar fragmento en Android

98

Estoy desarrollando una aplicación que contiene 2 fragmentos y quiero mostrar ocultar según mi necesidad. El siguiente código tiene un ejemplo simple de mi problema. Esta sencilla actividad de fragmentación contiene 1 botón y un fragmento de lista.

Este sencillo ejemplo funciona a la perfección. pero no estoy satisfecho con mostrar el fragmento de ocultar. Si elimina layout.setVisibility (View.GONE); del código luego ft.hide (f); no ocultará fragmentos. De hecho, no estamos escondiendo un fragmento, sino un contenedor.

Mi pregunta es, ¿ES esta una forma de mostrar fragmentos ocultos? Si no es así, explique con el ejemplo probado cómo ocultar y mostrar fragmentos porque muchas personas se enfrentan a este problema.

 public class MainActivity extends FragmentActivity implements OnClickListener {

        Fragment1 f;
        Button b;
        LinearLayout layout;
        Fragment myf;
        @Override
        public void onCreate(Bundle savedInstanceState){
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            b = (Button) findViewById(R.id.button1);
            layout = (LinearLayout) findViewById(R.id.ll);
            f = new Fragment1();
        }

        @Override
        public void onClick(View v) {

            FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
            ft.setCustomAnimations(android.R.animator.fade_in, android.R.animator.fade_out);

            if (f.isHidden()) {
                ft.show(f);
                layout.setVisibility(View.VISIBLE);
                b.setText("Hide");
            } else {
                ft.hide(f);
                b.setText("Show");
                layout.setVisibility(View.GONE);
            }
            ft.commit();
            // TODO Auto-generated method stub
        }
abidkhan303
fuente
¿Por qué necesita configurar la visibilidad del contenedor? Debería funcionar sin configurar la visibilidad.
Andrii Chernenko
Exactamente debería funcionar sin visibilidad del contenedor pero no está funcionando. Por favor, comparta conmigo un ejemplo de trabajo sencillo. Entonces sabría dónde me estoy perdiendo.
abidkhan303
1
Supongo que está tratando de mostrar / ocultar diferentes instancias de fragmentos cada vez. Cuando agrega su fragmento (no veo este fragmento de código, por cierto) agréguelo con la etiqueta y luego recupérelo por esa etiqueta (en lugar de intentar almacenar una referencia). Eso podría ser lo que te estás perdiendo.
Andrii Chernenko

Respuestas:

158

No se meta con las banderas de visibilidad del contenedor: FragmentTransaction.hide / show lo hace internamente por usted.

Entonces, la forma correcta de hacer esto es:

FragmentManager fm = getFragmentManager();
fm.beginTransaction()
          .setCustomAnimations(android.R.animator.fade_in, android.R.animator.fade_out)
          .show(somefrag)
          .commit();

O si está utilizando android.support.v4.app.Fragment

 FragmentManager fm = getSupportFragmentManager();
 fm.beginTransaction()
          .setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out)
          .show(somefrag)
          .commit();
numan salati
fuente
5
¿Por qué recomienda no jugar directamente con las banderas? (No estoy discutiendo tu recomendación, solo trato de entenderla.)
Ellen Spertus
1
Sí, lo leí en su mensaje original. Esperaba que pudiera agregar una justificación para los gastos generales adicionales. Mientras tanto, he descubierto algunos, como la opción de agregar a la pila de actividades.
Ellen Spertus
2
Es propenso a errores porque puede cambiar sus indicadores en la API de bajo nivel y en la API de alto nivel y si no tiene cuidado (es decir, las banderas no están sincronizadas), podría estar persiguiendo errores extraños. Es por eso que se recomienda utilizar el administrador de fragmentos para ocultar y mostrar sus fragmentos.
numan salati
@numansalati Hola, ¿hay alguna versión de compatibilidad (de la biblioteca de soporte) android.R.animator.fade_iny android.R.animator.fade_out?
Solace
1
Con el contenedor, puede configurarlo en MOSTRAR, OCULTAR o IDO. No existe la opción GONE al ocultar un fragmento.
Stealth Rabbi
57

Además, puede hacer en un Fragmento (por ejemplo, cuando fallaron los datos del servidor):

 getView().setVisibility(View.GONE);
Aria
fuente
11
Fragment es un elemento secundario de Object y no de View, por lo que no se puede llamar: fragment.setVisibility (View.INVISIBLE);
AndroidGeek
8
Arià está sugiriendo algo diferente, está sugiriendo obtener la vista desde ese fragmento y establecer su visibilidad en desaparecido.
AlvaroSantisteban
10
getView()Puede ser cuidadoso nullcuando aún no está inicializado.
TWiStErRob
22

Hola, lo hace utilizando este enfoque, todos los fragmentos permanecerán en el contenedor una vez agregados inicialmente y luego simplemente revelaremos el fragmento deseado y ocultamos los demás dentro del contenedor.

// Within an activity
private FragmentA fragmentA;
private FragmentB fragmentB;
private FragmentC fragmentC;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    if (savedInstanceState == null) {
        fragmentA = FragmentA.newInstance("foo");
        fragmentB = FragmentB.newInstance("bar");
        fragmentC = FragmentC.newInstance("baz");
    }
}


// Replace the switch method
protected void displayFragmentA() {
    FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
    if (fragmentA.isAdded()) { // if the fragment is already in container
        ft.show(fragmentA);
    } else { // fragment needs to be added to frame container
        ft.add(R.id.flContainer, fragmentA, "A");
    }
    // Hide fragment B
    if (fragmentB.isAdded()) { ft.hide(fragmentB); }
    // Hide fragment C
    if (fragmentC.isAdded()) { ft.hide(fragmentC); }
    // Commit changes
    ft.commit();
}

Consulte https://github.com/codepath/android_guides/wiki/Creating-and-Using-Fragments para obtener más información. Espero poder ayudar a cualquiera. Incluso si es una vieja pregunta.

mangu23
fuente
1
entonces tienes que tener dos métodos más como displayFragmentB () y displayFragmentC ()?
temirbek
sí @temirbek, puede seguir cómo se implementa el método displayFragmentA ().
mangu23
1
Si tiene muchos fragmentos en una actividad (2 o más) y está utilizando el método anterior, utilice este . Será más fácil de escribir y leer.
Maxime Claude
8
public void showHideFragment(final Fragment fragment){

    FragmentTransaction ft = getFragmentManager().beginTransaction();
    ft.setCustomAnimations(android.R.animator.fade_in,
                    android.R.animator.fade_out);

    if (fragment.isHidden()) {
        ft.show(fragment);
        Log.d("hidden","Show");
    } else {
        ft.hide(fragment);
        Log.d("Shown","Hide");                        
    }

    ft.commit();
}
Jyo el olor
fuente
1
correcto es ft.setCustomAnimations (android.R.anim.fade_in, android.R.anim.fade_out);
Webserveis
8

Prueba esto:

MapFragment mapFragment = (MapFragment)getFragmentManager().findFragmentById(R.id.mapview);
mapFragment.getView().setVisibility(View.GONE);
Ingo
fuente
2

Desde mi código, en comparación con la solución anterior, la forma más sencilla es definir un diseño que contenga el fragmento, luego puede ocultar o mostrar el fragmento controlando el atributo de diseño que está alineado con la forma de vista general. En este caso, no se necesita código adicional y los atributos de implementación adicionales del fragmento se pueden mover al diseño externo.

<LinearLayout style="@style/StHorizontalLinearView"
    >

    <fragment
        android:layout_width="match_parent"
        android:layout_height="390dp"
        android:layout_alignParentTop="true"
        />

</LinearLayout>
BrainAtom
fuente
0

Esto funcionó para mi

FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
        if(tag.equalsIgnoreCase("dashboard")){

            DashboardFragment dashboardFragment = (DashboardFragment)
                    fragmentManager.findFragmentByTag("dashboard");
            if(dashboardFragment!=null) ft.show(dashboardFragment);

            ShowcaseFragment showcaseFragment = (ShowcaseFragment)
                    fragmentManager.findFragmentByTag("showcase");
            if(showcaseFragment!=null) ft.hide(showcaseFragment);

        } else if(tag.equalsIgnoreCase("showcase")){
            DashboardFragment dashboardFragment = (DashboardFragment)
                    fragmentManager.findFragmentByTag("dashboard");
            if(dashboardFragment!=null) ft.hide(dashboardFragment);

            ShowcaseFragment showcaseFragment = (ShowcaseFragment)
                    fragmentManager.findFragmentByTag("showcase");
            if(showcaseFragment!=null) ft.show(showcaseFragment);
        }

        ft.commit();
Shankey
fuente
0

las respuestas aquí son correctas y me gustó @Jyo the Whiff idea de mostrar y ocultar la implementación de un fragmento, excepto que la forma en que lo tiene actualmente ocultaría el fragmento en la primera ejecución, así que agregué un ligero cambio en el que agregué la verificación y el espectáculo isAdded el fragmento si no es ya

public void showHideCardPreview(int id) {
    FragmentManager fm = getSupportFragmentManager();
    Bundle b = new Bundle();
    b.putInt(Constants.CARD, id);
    cardPreviewFragment.setArguments(b);
    FragmentTransaction ft = fm.beginTransaction()
        .setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out);
    if (!cardPreviewFragment.isAdded()){
        ft.add(R.id.full_screen_container, cardPreviewFragment);
        ft.show(cardPreviewFragment);
    } else {
        if (cardPreviewFragment.isHidden()) {
            Log.d(TAG,"++++++++++++++++++++ show");
            ft.show(cardPreviewFragment);
        } else {
            Log.d(TAG,"++++++++++++++++++++ hide");
            ft.hide(cardPreviewFragment);
        }
    }

    ft.commit();
} 
martinseal1987
fuente
0
final Fragment fragment1 = new fragment1();
final Fragment fragment2 = new fragment2();
final FragmentManager fm = getSupportFragmentManager();
Fragment active = fragment1;

En onCreate, después de setContentView, oculté dos fragmentos y los envié al administrador de fragmentos, pero no oculté el primer fragmento que servirá como hogar.

fm.beginTransaction().add(R.id.main_container, fragment2, "2").hide(fragment2).commit();
fm.beginTransaction().add(R.id.main_container,fragment1, "1").commit();
 @Override
    public void onClick(View v) {
        Fragment another = fragment1;
         if(active==fragment1){
          another = fragment2;
         }
            fm.beginTransaction().hide(active).show(another).commit();
            active = another;
}

Ref: https://medium.com/@oluwabukunmi.aluko/bottom-navigation-view-with-fragments-a074bfd08711

Rachit Vohera
fuente
0

Puede que sea demasiado tarde, pero podría ayudar a alguien en el futuro.
Esta respuesta es una modificación para mangu23 responder
Solo agregué un bucle for para evitar la repetición y para agregar fácilmente más fragmentos sin código repetitivo.

Primero necesitamos una lista de los fragmentos que deben mostrarse

public class MainActivity extends AppCompatActivity{
    //...
    List<Fragment> fragmentList = new ArrayList<>();
}

Entonces tenemos que llenarlo con nuestros fragmentos.

@Override
protected void onCreate(Bundle savedInstanceState) {
    //...
    HomeFragment homeFragment = new HomeFragment();
    MessagesFragment messagesFragment = new MessagesFragment();
    UserFragment userFragment = new UserFragment();
    FavoriteFragment favoriteFragment = new FavoriteFragment();
    MapFragment mapFragment = new MapFragment();

    fragmentList.add(homeFragment);
    fragmentList.add(messagesFragment);
    fragmentList.add(userFragment);
    fragmentList.add(favoriteFragment);
    fragmentList.add(mapFragment);
}

Y necesitamos una forma de saber qué fragmento se seleccionó de la lista, por lo que necesitamos getFragmentIndexfunción

private int getFragmentIndex(Fragment fragment) {
    int index = -1;
    for (int i = 0; i < fragmentList.size(); i++) {
        if (fragment.hashCode() == fragmentList.get(i).hashCode()){
            return i;
        }
    }
    return index;
}

Y finalmente, el displayFragmentmétodo será así:

private void displayFragment(Fragment fragment) {
        int index = getFragmentIndex(fragment);
        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
        if (fragment.isAdded()) { // if the fragment is already in container
            transaction.show(fragment);
        } else { // fragment needs to be added to frame container
            transaction.add(R.id.placeholder, fragment);
        }
        // hiding the other fragments
        for (int i = 0; i < fragmentList.size(); i++) {
            if (fragmentList.get(i).isAdded() && i != index) {
                transaction.hide(fragmentList.get(i));
            }
        }
        transaction.commit();
    }

De esta forma, podemos llamar displayFragment(homeFragment)por ejemplo.
Esto mostrará automáticamente HomeFragmenty ocultará cualquier otro fragmento en la lista.
Esta solución le permite agregar más fragmentos al fragmentListsin tener que repetir las ifdeclaraciones en la displayFragmentversión anterior.
Espero que alguien lo encuentre útil.

Mohamed Medhat
fuente