web-dev-qa-db-fra.com

Android: problème de chevauchement de fragments

Je suis confronté à un problème de chevauchement de fragments lorsque je passe d'un onglet à un autre et que j'attache des fragments à une vue d'onglet ci-dessous.

public class FragmentManage extends Fragment implements ActionBar.TabListener {

    private Fragment mFragment;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
            Bundle savedInstanceState) {

        View v = inflater.inflate(R.layout.fragment_manage, container, false);

        OnClickListener clickListener = new OnClickListener() { 
            public void onClick(View v) {
                FragmentTransaction ft = getFragmentManager().beginTransaction();
                switch(v.getId()) {
                    case R.id.imageBtnCategory:
                        if (mFragment == null){
                            mFragment = new FragmentCategory();
                        }
                        ft.replace(Android.R.id.content, mFragment);
                        break;
                    case R.id.imageBtnManageKey:
                        if (mFragment == null){
                            mFragment = new FragmentKeys();
                        }
                        ft.replace(Android.R.id.content, mFragment);
                        break;
                    case R.id.imageBtnChangePswd:
                        if (mFragment == null){
                            mFragment = new FragmentChangePwd();
                        }
                        ft.replace(Android.R.id.content, mFragment);
                        break;
                }
                ft.commit();
             }
        };

        ImageButton imageBtnCategory = (ImageButton) v.findViewById(R.id.imageBtnCategory);
        ImageButton imageBtnManageKey = (ImageButton) v.findViewById(R.id.imageBtnManageKey);
        ImageButton imageBtnChangePswd = (ImageButton) v.findViewById(R.id.imageBtnChangePswd);

        imageBtnCategory.setOnClickListener(clickListener);
        imageBtnManageKey.setOnClickListener(clickListener);
        imageBtnChangePswd.setOnClickListener(clickListener);

        return v;
    }

    public void onTabSelected(Tab tab, FragmentTransaction ft) {
        mFragment = new FragmentManage();
        ft.add(Android.R.id.content, mFragment);
        ft.attach(mFragment);
    }

    public void onTabUnselected(Tab tab, FragmentTransaction ft) {
        ft.remove(mFragment);
    }

    public void onTabReselected(Tab tab, FragmentTransaction ft) {

    }
}
32
girishawate

Définissez simplement une couleur d'arrière-plan pour votre <fragment /> dans un fichier XML.

Résout le problème.

84
kvh

Je serai peut-être très en retard pour répondre à cette question.

Remarque:

Cette réponse peut ne pas être liée à la question ci-dessus, mais j'espère que cela aidera certains.

Parfois, un problème de chevauchement de fragments se produit lorsque nous essayons d'utiliser les différents types de fragments (c'est-à-dire en utilisant des fragments de support en quelques fragments et des fragments normaux dans un autre fragment)

Récemment, j'ai rencontré le même problème dans le tiroir de navigation. Par erreur, j'ai utilisé "import Android.support.v4.app.Fragment;" dans un fragment, et utilisé "import Android.app.Fragment;" dans quelques autres fragment.

J'espère que cela aidera quelqu'un ..

15
Roshan

Eh bien, la configuration de la couleur d'arrière-plan du fragment n'est pas une solution car le fragment sera toujours dans la pile d'activités, ce qui peut consommer de la mémoire.

La solution serait de supprimer toutes les vues de votre framelayout avant d'ajouter un nouveau fragment.

private void changeFragment(Fragment fr){
    FrameLayout fl = (FrameLayout) findViewById(R.id.mainframe);
    fl.removeAllViews();
    FragmentTransaction transaction1 = getSupportFragmentManager().beginTransaction();
    transaction1.add(R.id.mainframe, fr);
    transaction1.commit();
}
10
Sufiyan Ansari

le gestionnaire de fragments conserve la pile de tous les fragments précédents qui sont remplacés parfois les fragments de la pile arrière chevauchent le fragment que nous avons remplacé, pour moi

  fragmentManager.popBackStack(); 

fonctionne, nous pouvons le faire en boucle aussi pour faire apparaître tous les fragments de la pile j'espère que cela aide, merci. Happy Coding :)

10
Syed Raza Mehdi

Un autre problème peut être lié à l'utilisation de Android.R.id.content comme conteneur. Je viens de créer FrameLayout et j'utilise id à partir de là.

4
irudyak

Voilà comment je l'ai corrigé ..

La définition de l'arrière-plan supprimerait l'effet de chevauchement de l'écran uniquement si la mise en page correspond à l'écran de remplissage

Les nouveaux fragments remplacés lors des clics sur les boutons n'étaient pas remplacés lors de l'action tab_selected ou tab change

le code suivant l'a corrigé pour moi

    public void onTabUnselected(Tab tab, FragmentTransaction ft) {
    // This is required since button click replaces fragment whose link is lost hence overlapping isuee was occuring
    ft.replace(Android.R.id.content, mFragment); 
    // On Tab Change remove old fragment views
    ft.remove(mFragment);
}
4
girishawate

J'ai également été confronté à un problème de chevauchement de fragments.Voici comment je l'ai résolu -

1) Nous devons ajouter le premier fragment avec addToBackStack, afin qu'il soit conservé dans la pile -

FirstFragment firstFragment = new FirstFragment();
getFragmentManager().beginTransaction().add(R.id.fragment_container, firstFragment).addToBackStack("first frag").commit();

2) Lors de l'ajout du deuxième fragment, remplacez le premier fragment plutôt que de l'ajouter. Puisque le premier fragment a déjà été ajouté dans la pile, il sera donc présent lorsque vous appuierez sur le deuxième fragment -

SecondFragment secondFragment= new SecondFragment();
getFragmentManager().beginTransaction().replace(R.id.fragment_container, secondFragment).addToBackStack("second frag").commit();

3) Voici comment gérer la contre-presse, le code ci-dessous doit être présent dans l'activité parent -

 public void onBackPressed(){
    if(getFragmentManager().getBackStackEntryCount() <= 1){
       super.onBackPressed();
    } else {
       getFragmentManager().popBackStack();
    }
 }
3
Sunita

Avez-vous vérifié votre XML et vu si la disposition principale est la disposition des cadres? Sinon, utilisez plutôt la disposition du cadre. Cela résoudra le problème de chevauchement. C'est la seule façon de réparer. J'ai essayé la réponse "acceptée" en cherchant une solution à ce problème et cela n'a pas fonctionné.

2
David Dimalanta
private void changeFragment(Fragment fr){
FrameLayout fl = (FrameLayout) findViewById(R.id.mainframe);
fl.removeAllViews();
FragmentTransaction transaction1 =getSupportFragmentManager().beginTransaction();
transaction1.add(R.id.mainframe, fr);
transaction1.commit();}
1
Mohit Taparia

J'ai parfois le même problème, mais mon problème n'est pas lié à différents gestionnaires de fragments (getSupportFragmentManager(), getFragmentManager()). Je pense qu'il y a encore un autre problème. Dans mon cas, lorsque j'ouvre le tiroir de navigation, je supprime toujours les anciens fragments sur chaque option de menu, par exemple:

Fragment calendarFragment = context.getSupportFragmentManager().findFragmentByTag(FragmentTag.CALENDAR.name());
if (calendarFragment != null)
{
    context.getSupportFragmentManager().beginTransaction().remove(calendarFragment).commit();
}

Il n'est pas possible d'accéder à un sous-menu sans le tiroir de navigation, donc les fragments sont fondamentalement toujours supprimés. Dans certains cas, après avoir supprimé et ajouté à nouveau un fragment dans une activité, il chevauche soudainement un autre fragment (précédent)?! Mais pourquoi le gestionnaire de fragments trouve-t-il soudain des fragments précédents? Cela peut signifier que le gestionnaire de fragments est bogué et qu'il ne supprime pas les anciens fragments, ou que quelque chose d'autre est cassé.
Ma pensée est que c'est en quelque sorte la faute de Android Studio ou tout autre outil de développement adb qui l'utilise. Pourquoi je pense que c'est parce que Android Studio semble parfois perdre l'instance de l'application en cours d'exécution. Ce problème est probablement lié au même problème: Android Studio ne déploie pas les modifications de l'application . Je n'ai pas encore compris Ce que je sais, c'est que cela ne peut pas être un problème de programmation, car il n'est pas reproductible après avoir relancé l'application par Android Studio. Je suppose qu'il y a en quelque sorte des processus d'arrière-plan qui se bloquent qui provoque plusieurs instances d'activités, de fragments, de gestionnaires de fragments, etc. par IDE).

0
Bevor

lorsque vous avez un fragment de chevauchement, peut-être que votre arrière-plan de votre fragment est transparent, vous devez mettre un Android: background = "@ color/white" 'à l'intérieur de vos propriétés de fragment

<FrameLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
xmlns:tools="http://schemas.Android.com/tools"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:background="@color/white"

et blanc, vous devez mettre à l'intérieur de colors.xml #FFFFFF dans le dossier de repos.

Je ne pense pas que la mise en œuvre d'un fond blanc soit une solution sûre bien qu'elle puisse être pratique. Fondamentalement, le problème se produit car le gestionnaire de fragments est confus quant au fragment à éclater.

backstack ressemble à ceci et pense que votre frag 4 1-> 2, 2-> 3, 3-> 4 mais votre fait sur frag 6 pour une raison quelconque, donc popbackstack va

supprimer (4) ajouter (3) <- maintenant vous avez 3(new) et 6 (à gauche) mélangés ensemble

Pour mieux contrôler ma navigation, je garde la trace de mes fragments actuels/précédents et je les remplace comme ceci. Cela permet à mon application de contrôler la navigation dans les fragments.

if ( !(currentFragment instanceof Settings)) {
        FragmentManager fragmentManager = getFragmentManager();
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        fragmentTransaction.replace(R.id.fragment_container, settings);
        fragmentTransaction.addToBackStack(null);
        previousFrag = currentFragment;
        currentFragment = settings;
        fragmentTransaction.commit();
    }

Deuxièmement, je pense que la méthode fragmentmanager.replace () est une meilleure alternative. Je ne sais pas si cela est disponible pour OP à l'époque.

Troisièmement, pour gérer la presse arrière native des androïdes, vous devez pouvoir revenir en arrière indéfiniment. Beaucoup de gens recommandent de ne pas ajouter le premier fragment à la pile arrière en n'utilisant pas cette ligne.

fragmentTransaction.addToBackStack (null);

Cependant, si c'est le cas, vous devez vérifier si c'est la première fois que l'application est chargée. Si ce n'est pas le cas et que vous excluez cette ligne, votre application rencontrera ces problèmes chaque fois que vous naviguerez dans ce fragment. Je préfère le laisser en place et faire à la place ce qui suit.

Je ne sais pas si cela est considéré comme une bonne solution mais cela fonctionne très bien.

1- obtenir le nombre de backstack 2- supprimer tous les frags existants 3- garder une trace de vos objets fragmentés 4- si c'est le dernier fragment de la pile, l'utilisateur souhaite quitter et puisque nous avons ajouté l'activité principale à la pile arrière, nous devons doubler

@Override
public void onBackPressed() {

int num = getFragmentManager().getBackStackEntryCount();


        fl.removeAllViews();
        super.onBackPressed();

        if  (currentFragment != previousFrag) {
            currentFragment = previousFrag;
        }else{
            currentFragment = null;
        }

        if (num == 1){
           super.onBackPressed();
        }
0
cagney

Tout cela a à voir avec l'ingénierie derrière les méthodes replace et addToBackStack.

La méthode replace fera en fait deux choses. Cachez le fragment existant (disons A) et ajoutez-en un nouveau (disons B) dans le conteneur.

Ajouter cette transaction à la pile arrière fera le contraire. Supprimer B et ajouter A.

Donc, la solution à votre problème est
1. utilisez la méthode addToBackStack.
2. assurez-vous que le remplacement inverse des fragments est le bon ordre

La deuxième suggestion est vraiment importante, car il arrive assez souvent qu'à un moment donné, le fragment actuel ne soit pas supprimé et qu'un autre soit ajouté, ce qui fait apparaître les deux fragments en même temps.

0
ichalos

J'ai trouvé une solution simple et propre. Pour moi, le problème était dans la transaction de fragment d'exécution à chaque appel de onCreate () de mon activité. Maintenant, j'effectue une transaction uniquement si saveInstanceState == null

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        if (savedInstanceState == null) {
        // replace fragment 
        }
    }
0
Ivan Syabro

Rendre la couleur de fond blanche l'a aussi résolu pour moi. Je pense que c'est un bug ou un problème d'implémentation dans le gestionnaire de fragment Android Android. J'implémentais correctement replace et popBackStack ().

0
daniekpo

Quand j'ai eu un problème comme celui-ci, il est apparu que j'ajoutais un fragment avec childFragmentManager et un autre avec le fragmentManager du parent, alors vérifiez que vous utilisez le même type de gestionnaire de fragments.

0
Olga Sokol