Afficher le fragment de masquage dans Android

99

Je développe une application qui contient 2 fragments et je souhaite afficher le masque en fonction de mes besoins. Le code suivant a un exemple simple de mon problème. Cette activité Fragmentaire simple contient 1 bouton et un fragment de liste.

Cet exemple simple fonctionne parfaitement. mais je ne suis pas satisfait de show hide fragment. Si vous supprimez layout.setVisibility (View.GONE); à partir du code puis ft.hide (f); ne cachera pas le fragment. En fait, nous ne cachons pas le fragment que nous cachons le conteneur.

Ma question est la suivante: est-ce un moyen d'afficher des fragments de masquage? Sinon, veuillez expliquer avec un exemple testé Comment masquer et afficher des fragments car de nombreuses personnes sont confrontées à ce problème.

 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
la source
Pourquoi avez-vous besoin de définir la visibilité du conteneur? Cela devrait fonctionner sans définir de visibilité.
Andrii Chernenko
Exactement, cela devrait fonctionner sans visibilité du conteneur mais cela ne fonctionne pas. Veuillez s'il vous plaît partager un exemple de travail simple avec moi. Alors je saurais où je manque.
abidkhan303
1
Je suppose que vous essayez d'afficher / masquer une instance différente de fragment à chaque fois. Lorsque vous ajoutez votre fragment (je ne vois pas ce morceau de code, au fait), ajoutez-le avec une balise, puis récupérez-le par cette balise (au lieu d'essayer de stocker une référence). C'est peut-être ce qui vous manque.
Andrii Chernenko

Réponses:

159

Ne jouez pas avec les indicateurs de visibilité du conteneur - FragmentTransaction.hide / show le fait en interne pour vous.

La bonne façon de procéder est donc:

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

OU si vous utilisez 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
la source
5
Pourquoi déconseillez-vous de jouer directement avec les drapeaux? (Je ne conteste pas votre recommandation, j'essaie juste de la comprendre.)
Ellen Spertus
1
Oui, je l'ai lu dans votre message d'origine. J'espérais que vous pourriez ajouter une justification pour les frais généraux supplémentaires. En attendant, j'en ai découvert quelques-uns, comme l'option d'ajouter à la pile arrière.
Ellen Spertus
2
Il est sujet aux erreurs car vous pouvez changer vos indicateurs à l'API de bas niveau et à l'API de haut niveau et si vous ne faites pas attention (c'est-à-dire que les indicateurs ne sont pas synchronisés), vous pourriez chasser des bogues étranges. C'est pourquoi il est recommandé d'utiliser le gestionnaire de fragments pour masquer et afficher vos fragments.
numan salati
@numansalati Salut, y a-t-il une version de compatibilité (de la bibliothèque de support) de android.R.animator.fade_in, et android.R.animator.fade_out?
Solace
1
Avec le conteneur, vous pouvez le définir sur SHOW, HIDE ou GONE. Il n'y a pas d'option GONE lors du masquage d'un fragment.
Stealth Rabbi
57

De plus, vous pouvez faire dans un fragment (par exemple lorsque l'obtention des données du serveur a échoué):

 getView().setVisibility(View.GONE);
Aria
la source
11
Fragment est un enfant d'Object et non de View, donc on ne peut pas appeler: fragment.setVisibility (View.INVISIBLE);
AndroidGeek
8
Arià suggère quelque chose de différent, suggère d'obtenir la vue de ce fragment et de définir sa visibilité sur disparu.
AlvaroSantisteban
10
Attention getView()peut-être nullquand il n'est pas encore initialisé.
TWiStErRob
22

Salut, vous le faites en utilisant cette approche, tous les fragments resteront dans le conteneur une fois ajoutés initialement, puis nous révélons simplement le fragment souhaité et masquons les autres dans le conteneur.

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

Veuillez consulter https://github.com/codepath/android_guides/wiki/Creating-and-Using-Fragments pour plus d'informations. J'espère pouvoir aider n'importe qui. Même si c'est une vieille question.

mangu23
la source
1
vous devez donc avoir deux méthodes supplémentaires comme displayFragmentB () et displayFragmentC ()?
temirbek le
oui @temirbek vous pouvez simplement suivre comment la méthode displayFragmentA () est implémentée.
mangu23
1
Si vous avez plusieurs fragments dans une activité (2 ou plus) et que vous utilisez la méthode ci-dessus, veuillez utiliser ceci . Ce sera plus facile à écrire et à lire.
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 l'odeur
la source
1
correct est ft.setCustomAnimations (android.R.anim.fade_in, android.R.anim.fade_out);
Webserveis
8

Essaye ça:

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

À partir de mon code, par rapport à la solution ci-dessus, le moyen le plus simple est de définir une mise en page contenant le fragment, puis vous pouvez masquer ou afficher le fragment en contrôlant l'attribut de mise en page qui est aligné sur le mode de vue général. Aucun code supplémentaire n'est nécessaire dans ce cas et les attributs de déploiement supplémentaires du fragment peuvent être déplacés vers la mise en page externe.

<LinearLayout style="@style/StHorizontalLinearView"
    >

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

</LinearLayout>
CerveauAtom
la source
0

Cela a fonctionné pour moi

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
la source
0

les réponses ici sont correctes et j'ai aimé @Jyo l'idée Whiff d'une implémentation de fragment d'affichage et de masquage, sauf que la façon dont il l'a actuellement masquerait le fragment lors de la première exécution, j'ai donc ajouté un léger changement en ce que j'ai ajouté la vérification et l'affichage isAdded le fragment si ce n'est pas déjà

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
la source
0
final Fragment fragment1 = new fragment1();
final Fragment fragment2 = new fragment2();
final FragmentManager fm = getSupportFragmentManager();
Fragment active = fragment1;

Dans onCreate, après setContentView, j'ai caché deux fragments et les ai commis dans le gestionnaire de fragments, mais je n'ai pas caché le premier fragment qui servira de domicile.

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

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

Rachit Vohera
la source
0

Je suis peut-être bien trop tard, mais cela pourrait aider quelqu'un à l'avenir.
Cette réponse est une modification pour mangu23 répondre
J'ai seulement ajouté une boucle for pour éviter la répétition et pour ajouter facilement plus de fragments sans code standard.

Nous avons d'abord besoin d'une liste des fragments à afficher

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

Ensuite, nous devons le remplir de nos fragments

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

Et nous avons besoin d'un moyen de savoir quel fragment a été sélectionné dans la liste, nous avons donc besoin de getFragmentIndexfonction

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

Et enfin, la displayFragmentméthode aimera ceci:

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 cette façon, nous pouvons appeler displayFragment(homeFragment)par exemple.
Cela affichera HomeFragmentet masquera automatiquement tout autre fragment de la liste.
Cette solution vous permet d'ajouter plus de fragments au fragmentListsans avoir à répéter les ifinstructions de l'ancienne displayFragmentversion.
J'espère que quelqu'un trouvera cela utile.

Mohamed Medhat
la source