Fragment Inside Fragment

J’ai besoin d’aide pour travailler sur fragment à l’intérieur du fragment, en fait, je suis confronté à un problème en appuyant sur le bouton Retour. Application écran principal a des boutons et en appuyant sur chaque bouton, remplacer par un nouveau fragment (et ce fragment contient à l’intérieur d’un autre fragment), l’ajout / remplacement dynamic de fragment fonctionne correctement, en appuyant sur bouton1 fragment remplacé, même chose le bouton à nouveau, a une exception:

"Duplicate id 0x7f05000a, tag null, or parent id 0x7f050009 with another fragment for com........ fragmentname" 

Cela signifie que des fragments ou des fragments internes sont déjà ajoutés et j’essaie de les append à nouveau, tout le monde a une idée de comment travailler avec fragment à l’intérieur de fragment et se déplacer sans problème, merci pour le support.

MainActivity, où les fragments sont ajoutés dynamicment et remplacés.

  public class FragmentInsideFragmentTestActivity extends Activity { private Button button1; private Button button2; private Button button3; private Button button4; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); button1 =(Button) this.findViewById(R.id.button1); button1.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { onButtonClick(view); } }); button2 =(Button) this.findViewById(R.id.button2); button2.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { onButtonClick(view); } }); button3 =(Button) this.findViewById(R.id.button3); button3.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { onButtonClick(view); } }); button4 =(Button) this.findViewById(R.id.button4); button4.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { onButtonClick(view); } }); } public void onButtonClick(View v) { Fragment fg; switch (v.getId()) { case R.id.button1: fg=FirstFragment.newInstance(); replaceFragment(fg); break; case R.id.button2: fg=SecondFragment.newInstance(); replaceFragment(fg); break; case R.id.button3: fg=FirstFragment.newInstance(); replaceFragment(fg); break; case R.id.button4: fg=SecondFragment.newInstance(); replaceFragment(fg); break; } } private void replaceFragment(Fragment newFragment) { FragmentTransaction trasection = getFragmentManager().beginTransaction(); if(!newFragment.isAdded()){ try{ //FragmentTransaction trasection = getFragmentManager().beginTransaction(); trasection.replace(R.id.linearLayout2, newFragment); trasection.addToBackStack(null); trasection.commit(); }catch (Exception e) { // TODO: handle exception //AppConstants.printLog(e.getMessage()); } }else trasection.show(newFragment); } } 

Voici Layout: main.xml

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

J’espère que j’ai essayé de résoudre mon problème.

AFAIK, les fragments ne peuvent pas contenir d’autres fragments.


METTRE À JOUR

Avec les versions actuelles du package de support Android – ou des fragments natifs sur API niveau 17 et supérieur – vous pouvez imbriquer des fragments au moyen de getChildFragmentManager() . Notez que cela signifie que vous devez utiliser la version du package Support Android pour les fragments aux niveaux API 11 à 16, car même s’il existe une version native des fragments sur ces périphériques, cette version n’a pas getChildFragmentManager() .

Depuis Android 4.2 (API 17), des fragments nesteds sont disponibles http://developer.android.com/about/versions/android-4.2.html#NestedFragments

Pour placer un fragment dans un autre fragment, utilisez getChildFragmentManager ()

Il est également disponible dans la bibliothèque de support!

entrer la description de l'image ici

J’avais besoin d’un peu plus de contexte, alors j’ai fait un exemple pour montrer comment cela se fait. La chose la plus utile que je lisais pendant la préparation était la suivante:

  • Création et utilisation de fragments

Activité

activity_main.xml

Ajoutez un FrameLayout à votre activité pour contenir le fragment parent.

      

MainActivity.java

Chargez le fragment parent et implémentez les écouteurs fragment. (Voir la communication par fragment .)

 import android.support.v4.app.FragmentTransaction; import android.support.v7.app.AppCompatActivity; public class MainActivity extends AppCompatActivity implements ParentFragment.OnFragmentInteractionListener, ChildFragment.OnFragmentInteractionListener { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Begin the transaction FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); ft.replace(R.id.parent_fragment_container, new ParentFragment()); ft.commit(); } @Override public void messageFromParentFragment(Uri uri) { Log.i("TAG", "received communication from parent fragment"); } @Override public void messageFromChildFragment(Uri uri) { Log.i("TAG", "received communication from child fragment"); } } 

Fragment de parent

fragment_parent.xml

Ajoutez un autre conteneur FrameLayout pour le fragment enfant.

       

ParentFragment.java

Utilisez getChildFragmentManager dans onViewCreated pour configurer le fragment enfant.

 import android.support.v4.app.Fragment; import android.support.v4.app.FragmentTransaction; public class ParentFragment extends Fragment { private OnFragmentInteractionListener mListener; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment return inflater.inflate(R.layout.fragment_parent, container, false); } @Override public void onViewCreated(View view, Bundle savedInstanceState) { Fragment childFragment = new ChildFragment(); FragmentTransaction transaction = getChildFragmentManager().beginTransaction(); transaction.replace(R.id.child_fragment_container, childFragment).commit(); } @Override public void onAttach(Context context) { super.onAttach(context); if (context instanceof OnFragmentInteractionListener) { mListener = (OnFragmentInteractionListener) context; } else { throw new RuntimeException(context.toSsortingng() + " must implement OnFragmentInteractionListener"); } } @Override public void onDetach() { super.onDetach(); mListener = null; } public interface OnFragmentInteractionListener { // TODO: Update argument type and name void messageFromParentFragment(Uri uri); } } 

Fragment d’enfant

fragment_child.xml

Il n’y a rien de spécial ici.

     

ChildFragment.java

Il n’y a rien de trop spécial ici non plus.

 import android.support.v4.app.Fragment; public class ChildFragment extends Fragment { private OnFragmentInteractionListener mListener; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_child, container, false); } @Override public void onAttach(Context context) { super.onAttach(context); if (context instanceof OnFragmentInteractionListener) { mListener = (OnFragmentInteractionListener) context; } else { throw new RuntimeException(context.toSsortingng() + " must implement OnFragmentInteractionListener"); } } @Override public void onDetach() { super.onDetach(); mListener = null; } public interface OnFragmentInteractionListener { // TODO: Update argument type and name void messageFromChildFragment(Uri uri); } } 

Remarques

  • La bibliothèque de support est utilisée pour que les fragments nesteds puissent être utilisés avant Android 4.2.

Des fragments peuvent être ajoutés à l’intérieur d’autres fragments, mais vous devrez ensuite les supprimer du fragment parent chaque fois que la méthode onDestroyView () du fragment parent est appelée. Et encore l’append dans la méthode OnCreateView () de Parent Fragment.

Faites comme ça:

 @Override public void onDestroyView() { FragmentManager mFragmentMgr= getFragmentManager(); FragmentTransaction mTransaction = mFragmentMgr.beginTransaction(); Fragment childFragment =mFragmentMgr.findFragmentByTag("qa_fragment") mTransaction.remove(childFragment); mTransaction.commit(); super.onDestroyView(); } 

J’ai résolu ce problème. Vous pouvez utiliser la bibliothèque de support et ViewPager . Si vous n’avez pas besoin de glisser par geste, vous pouvez désactiver le balayage. Voici donc un code pour améliorer ma solution:

 public class TestFragment extends Fragment{ @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View v = inflater.inflate(R.layout.frag, container, false); final ArrayList list = new ArrayList(); list.add(new TrFrag()); list.add(new TrFrag()); list.add(new TrFrag()); ViewPager pager = (ViewPager) v.findViewById(R.id.pager); pager.setAdapter(new FragmentPagerAdapter(getChildFragmentManager()) { @Override public Fragment getItem(int i) { return list.get(i); } @Override public int getCount() { return list.size(); } }); return v; } } 

PSIt est un code laid pour le test, mais il améliore que c’est possible.

Fragment PPS Inside ChildFragmentManager doit être transmis à ViewPagerAdapter

vous pouvez utiliser la fonction getChildFragmentManager() .

Exemple:

Fragment parent:

 @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { rootView = inflater.inflate(R.layout.parent_fragment, container, false); } //child fragment FragmentManager childFragMan = getChildFragmentManager(); FragmentTransaction childFragTrans = childFragMan.beginTransaction(); ChildFragment fragB = new ChildFragment (); childFragTrans.add(R.id.FRAGMENT_PLACEHOLDER, fragB); childFragTrans.addToBackStack("B"); childFragTrans.commit(); return rootView; } 

Mise en page parent ( parent_fragment.xml ):

     

Fragment d’enfant:

 public class ChildFragment extends Fragment implements View.OnClickListener{ View v ; @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { // TODO Auto-generated method stub View rootView = inflater.inflate(R.layout.child_fragment, container, false); v = rootView; return rootView; } @Override public void onClick(View view) { } } 

Vous pouvez append FrameLayout au fragment et le remplacer par un autre fragment lors de son initialisation.

De cette façon, vous pourriez considérer l’autre fragment à l’intérieur du premier fragment.

Utilisez getChildFragmentManager (), suivez le lien: Fragment nested

Il n’ya pas de support pour MapFragment, l’équipe Android y travaille depuis Android 3.0. Voici plus d’informations sur le problème: http://code.google.com/p/android/issues/detail?id=15347&utm_source=buffer&buffer_share=acc72 Mais vous pouvez le faire en créant un fragment qui renvoie un MapActivity. Voici un exemple de code. Merci à inazaruk: https://github.com/inazaruk/examples/tree/master/MapFragmentExample

Comment ça marche:

-MainFragmentActivity est l’activité qui étend FragmentActivity et héberge deux MapFragments. -MyMapActivity étend MapActivity et dispose de MapView. -LocalActivityManagerFragment héberge LocalActivityManager. -MyMapFragment étend LocalActivityManagerFragment et, avec l’aide de TabHost, crée une instance interne de MyMapActivity. Si vous avez le moindre doute, faites le moi savoir

Dans le fragment nested, le ou les nesteds ne sont pris en charge que s’ils sont générés par programme! Donc, à ce stade, aucune disposition de fragments nesteds n’est prise en charge dans le schéma de présentation XML!

Ce n’est pas compliqué. Nous ne pouvons pas utiliser getFragmentManager () ici. Pour utiliser Fragments dans un fragment, nous utilisons getChildFragmentManager (). Le repos sera le même.

Salut, j’ai résolu ce problème en mettant par fragment dans la mise en page distincte. Et j’ai juste rendu visible la mise en page et rendu les autres visibilités.

Je veux dire:

               . . .  

Je suppose que vous allez ouvrir votre page en cliquant sur le bouton 1. Vous pouvez contrôler les visibilités de votre fragment en cliquant dessus. Vous pouvez rendre la mise en page apparentée et les autres disparus et par Fragment Manager vous pouvez prendre votre fragment. Cette approche a fonctionné pour moi. Et puisque la vue qui a de la visibilité: disparue est invisible et ne prend pas de place pour la mise en page, je pense que cette approche ne pose aucun problème d’espace.

PS: J’ai juste essayé d’expliquer que le code de ma solution peut comporter des erreurs de syntaxe ou une structure incomplète.

Cela peut aider ceux qui travaillent sur Kotlin, vous pouvez utiliser la fonction d’extension, alors créez un fichier kotlin, disons “util.kt” et ajoutez ce morceau de code

 fun Fragment.addChildFragment(fragment: Fragment, frameId: Int) { val transaction = childFragmentManager.beginTransaction() transaction.replace(frameId, fragment).commit() } 

Disons que c’est la classe de l’ enfant

 class InputFieldPresentation: Fragment() { var views: View? = null override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? { views = inflater!!.inflate(R.layout.input_field_frag, container, false) return views } override fun onViewCreated(view: View?, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) ... } ... } 

Maintenant, vous pouvez append les enfants au fragment de père comme celui-ci

  FatherPresentation:Fragment() { ... override fun onViewCreated(view: View?, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) val fieldFragment= InputFieldPresentation() addChildFragment(fieldFragment,R.id.fragmet_field) } ... } 

R.id.fragmet_field est l’id de la mise en page qui contiendra le fragment. Voici un exemple

père_fragment.xml :

  ...   ...