web-dev-qa-db-fra.com

Duplication de fragments sur une transaction de fragments

D'accord, chaque fois que j'essaie de remplacer un fragment dans mon application, cela ne fait qu'ajouter le fragment à l'intérieur du conteneur que contient l'autre fragment et laisser le fragment actuel. J'ai essayé d'appeler replace et de référencer la vue qui contient le fragment et de référencer le fragment lui-même. Ni l'un ni l'autre ne fonctionne. Je peux ajouter un fragment à une vue avec le gestionnaire de transactions fragment, mais même si j'essaie de le supprimer après l'avoir ajouté, cela ne fonctionne pas. Toute aide serait appréciée. Voici mes fichiers.

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    //Setup the actionabar. Use setDrawableBackground to set a background image for the actionbar.
    final ActionBar actionbar = getActionBar();
    actionbar.setDisplayShowTitleEnabled(false);
    actionbar.setDisplayUseLogoEnabled(true);
    actionbar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
    actionbar.addTab(actionbar.newTab().setText(R.string.home_tab_text).setTabListener(this),true);
    actionbar.addTab(actionbar.newTab().setText(R.string.insert_tab_text).setTabListener(this));

    Fragment fragment = new insert_button_frag();
    FragmentTransaction transaction = getFragmentManager().beginTransaction();
    transaction.replace(R.id.button_fragment, fragment);
    transaction.addToBackStack(null);

    transaction.commit();
}

Voici la mise en page

<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:orientation="vertical"
    Android:layout_width="fill_parent"
    Android:layout_height="fill_parent">

    <LinearLayout
        Android:orientation="vertical"
        Android:id="@+id/button_fragment_container"
        Android:layout_width="fill_parent"
        Android:layout_height="wrap_content" >

        <fragment
            Android:name="com.bv.silveredittab.home_button_frag"
            Android:id="@+id/button_fragment"
            Android:layout_width="fill_parent"
            Android:layout_height="wrap_content" />

    </LinearLayout>

    <LinearLayout
        Android:orientation="horizontal"
        Android:layout_width="fill_parent"
        Android:layout_height="fill_parent" >

        <fragment
            Android:name="com.bv.silveredittab.quick_insert_frag"
            Android:id="@+id/quick_insert_frag"
            Android:layout_width="350dip"
            Android:layout_height="fill_parent" />

        <fragment
            Android:name="com.bv.silveredittab.editor_frag"
            Android:id="@+id/editor_frag"
            Android:layout_width="fill_parent"
            Android:layout_height="fill_parent" />

    </LinearLayout>

</LinearLayout>

Et voici le code de fragment

public class insert_button_frag extends Fragment {

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        return inflater.inflate(R.layout.insert_buttons,container, false);
    }
}

Comme je l'ai dit. J'ai essayé de référencer la vue parent de fragments pour la remplacer, ainsi que le fragment lui-même (par id) et, néanmoins, il ajoute seulement le nouveau fragment, dans la vue contenant le fragment d'origine.

45
Shaun

J'ai résolu ce problème en utilisant un espace réservé dans ma mise en page, puis en y attachant mon fragment au moment de l'exécution.

Comme vous, si j'instanciais mon fragment dans ma mise en page XML, le contenu resterait visible après l'avoir remplacé par un autre fragment au moment de l'exécution.

33
Damian

Le problème est cette ligne:

transaction.replace(R.id.button_fragment, fragment);

replace a deux formulaires surchargés. Dans les deux cas, le premier argument est le conteneur du fragment à remplacer, pas le fragment lui-même. Donc, dans votre cas, vous devez appeler

transaction.replace(R.id.button_fragment_container, fragment);

edit: je vois dans votre question que vous avez essayé les deux. J'ai testé et vérifié le comportement. Cela semble être un bogue dans l'API FragmentTransaction.

Edit2: pas un bug après tout. Vous ne pouvez simplement pas remplacer des fragments ajoutés de manière statique dans un fichier de mise en page. Vous ne pouvez remplacer que ceux que vous avez ajoutés par programme ( Android: impossible de remplacer un fragment par un autre )

18
Brian Cooley

J'ai eu le même problème. Jetez un oeil à ce lien: Duplication de fragment Android

Je me demande si le fait de passer le conteneur dans la méthode inflater.inflate () le force à créer le nouveau fragment à l'intérieur de l'ancien au lieu d'un remplacement en gros. J'ai fourni "null" à mes inflaters dans la version de travail.

Voici l'essentiel de la version que je travaille ...

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
   View newFrag = new View(getActivity().getApplicationContext());
   newFrag = inflater.inflate(R.id.frag, null);
   return newFrag;
}
2
Peter

Le (guide du développeur Google) est assez déroutant car il montre d’abord comment implémenter un fragment codé en dur dans votre fichier xml. Mais si vous voulez vraiment remplacer le fragment existant par le nouveau, vous devez l’ajouter (le premier) au moment de l’exécution.

Quel est l'état de { site officiel } _ 

FragmentTransaction replace (int conteneurViewId, fragment de fragment, balise String)

Remplacer un fragment existant qui a été ajouté à un conteneur. C'est essentiellement le même que l'appelant supprimer (Fragment) pour tous actuellement ajouté des fragments qui ont été ajoutés avec le même conteneurViewId, puis add (int, Fragment, String) avec les mêmes arguments que ceux donnés ici.

Vous devriez remarquer qu'il dit que remplace un fragment existant que a été ajouté au conteneur

Ainsi, votre fichier xml devrait ressembler à someActivity.xml

<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    ...
    tools:context="someActivity">

    <ImageView
        .../>

    <LinearLayout
        Android:id="@+id/fragment_container"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        Android:orientation="vertical"
        Android:gravity="bottom"/>

</RelativeLayout>

Et que dans votre activité faites dans OnCreate ()

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        [...]
        getSupportFragmentManager().beginTransaction()
                .add(R.id.fragment_container, new FirstFragment).commit();

    }

Ensuite, vous pouvez facilement remplacer fragment par vos animations et l'événement, ajoutez-le à la pile arrière afin de sauvegarder son état.

private SecondFrag getSecondFrag(){
    if(secondFrag == null)
        secondFrag = new SecondFrag()
    return secondFrag;
}

private void openRechargeFragment(){
        FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
        ft.setCustomAnimations(R.anim.show_frag, R.anim.hide_frag,
                R.anim.show_frag, R.anim.hide_frag);
        ft.replace(R.id.fragment_container, getSecondFrag(), "myTAG");
        ft.addToBackStack(null);
        ft.commit();
}
0
murt