Fragmento Dentro del Fragmento


Necesito ayuda con respecto a trabajar en fragmento dentro de fragmento, en realidad Yo estoy enfrentando un problema al presionar el botón atrás. Pantalla principal de la aplicación tiene botones y presionando en cada vista de botón reemplazar con nuevo fragmento (y ese fragmento contiene dentro de otro fragmento), agregar/reemplazar fragmentos dinámicamente funciona bien, presionando fragmento button1 reemplazado, lo mismo sucede al presionar el botón, pero si Presiono el botón de nuevo, tengo una excepción:

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

Significa fragmento o interior fragmentos ya se han añadido y estoy tratando para añadirlos de nuevo, cualquiera tiene idea de cómo trabajar con fragment inside fragmento y moviéndose hacia adelante y hacia atrás sin ningún problema, gracias por el apoyo.

MainActivity, donde se añaden fragmentos dinámicos y reemplazar.

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

      }
    }

Aquí está el diseño: principal.xml

 <?xml version="1.0" encoding="utf-8"?>
 <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:id="@+id/linearLayout1"
           android:layout_width="match_parent"
           android:layout_height="wrap_content"
           android:orientation="horizontal">
           <Button android:layout_width="wrap_content"
                   android:id="@+id/button1"
                   android:layout_height="wrap_content"
                   android:text="Button1"></Button>
           <Button android:text="Button2"
                   android:id="@+id/button2"
                   android:layout_width="wrap_content"
                   android:layout_height="wrap_content"></Button>
           <Button android:text="Button3"
                   android:id="@+id/button3"
                   android:layout_width="wrap_content"
                   android:layout_height="wrap_content"></Button>
           <Button android:text="Button4"
                   android:id="@+id/button4"
                   android:layout_width="wrap_content"
                   android:layout_height="wrap_content"></Button>
   </LinearLayout>

  <LinearLayout android:id="@+id/linearLayout2"
   android:layout_width="match_parent"
    android:layout_height="wrap_content"
   android:orientation="horizontal"></LinearLayout>
     </LinearLayout>

Espero haber tratado de aclarar mi problema.

Author: Fllo, 2011-07-13

13 answers

AFAIK, los fragmentos no pueden contener otros fragmentos.


ACTUALIZACIÓN

Con las versiones actuales del paquete de soporte de Android -- o fragmentos nativos en el nivel de API 17 y superior can puede anidar fragmentos, mediante getChildFragmentManager(). Tenga en cuenta que esto significa que debe usar la versión del paquete de soporte de Android de fragments en los niveles de API 11-16, porque a pesar de que hay una versión nativa de fragments en esos dispositivos, esa versión no tiene getChildFragmentManager().

 237
Author: CommonsWare,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-12-16 12:05:43

Desde Android 4.2 (API 17) los fragmentos anidados están disponibles http://developer.android.com/about/versions/android-4.2.html#NestedFragments

Para colocar el fragmento dentro de otro fragmento use getChildFragmentManager ()

También está disponible en la biblioteca de soporte!

 60
Author: Nik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-30 15:43:22

introduzca la descripción de la imagen aquí

Necesitaba un poco más de contexto, así que hice un ejemplo para mostrar cómo se hace esto. Lo más útil que leí mientras me preparaba fue esto:

Actividad

activity_main.xml

Agrega un FrameLayout a tu actividad para contener el fragmento padre.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Activity"/>

    <FrameLayout
        android:id="@+id/parent_fragment_container"
        android:layout_width="match_parent"
        android:layout_height="200dp"/>

 </LinearLayout>

MainActivity.java

Cargue el fragmento padre y implementa los oyentes de fragmentos. (Ver fragmento de comunicación.)

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

Fragmento padre

fragment_parent.xml

Agregue otro contenedor FrameLayout para el fragmento hijo.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:layout_margin="20dp"
              android:background="#91d0c2">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Parent fragment"/>

    <FrameLayout
        android:id="@+id/child_fragment_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    </FrameLayout>

</LinearLayout>

ParentFragment.java

Use getChildFragmentManager en onViewCreated para configurar el fragmento hijo.

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.toString()
                    + " must implement OnFragmentInteractionListener");
        }
    }

    @Override
    public void onDetach() {
        super.onDetach();
        mListener = null;
    }

    public interface OnFragmentInteractionListener {
        // TODO: Update argument type and name
        void messageFromParentFragment(Uri uri);
    }
}

Fragmento hijo

fragment_child.xml

No Hay nada especial aqui.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:layout_margin="20dp"
              android:background="#f1ff91">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Child fragment"/>
</LinearLayout>

ChildFragment.java

Aquí tampoco hay nada demasiado especial.

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.toString()
                    + " must implement OnFragmentInteractionListener");
        }
    }

    @Override
    public void onDetach() {
        super.onDetach();
        mListener = null;
    }


    public interface OnFragmentInteractionListener {
        // TODO: Update argument type and name
        void messageFromChildFragment(Uri uri);
    }
}

Notas

 46
Author: Suragch,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-09-13 10:29:16

Los fragmentos se pueden agregar dentro de otros fragmentos, pero luego deberá eliminarlos del fragmento padre cada vez que se llame al método onDestroyView() del fragmento padre. Y otra vez agrégalo en el método onCreateView() del fragmento padre.

Simplemente haz lo siguiente:

@Override
    public void onDestroyView()
    {
                FragmentManager mFragmentMgr= getFragmentManager();
        FragmentTransaction mTransaction = mFragmentMgr.beginTransaction();
                Fragment childFragment =mFragmentMgr.findFragmentByTag("qa_fragment")
        mTransaction.remove(childFragment);
        mTransaction.commit();
        super.onDestroyView();
    }
 11
Author: Napolean,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-08-23 10:10:07

Resolví este problema. Puede utilizar la biblioteca de soporte y ViewPager. Si no necesita deslizar por gesto, puede desactivar el deslizar. Así que aquí hay un código para mejorar mi solución:

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<Fragment> list = new ArrayList<Fragment>();

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

P.S.It es código feo para la prueba, pero mejora que es posible.

P. P. S Dentro del fragmento ChildFragmentManager debe pasarse a ViewPagerAdapter

 8
Author: Vetalll,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-12-12 15:28:29

Puede usar la función getChildFragmentManager().

Ejemplo:

Fragmento padre:

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

Diseño padre(parent_fragment.xml):

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/white">



    <FrameLayout
        android:id="@+id/FRAGMENT_PLACEHOLDER"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>




</LinearLayout>

Fragmento hijo:

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) {


    }


} 
 4
Author: S.M_Emamian,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-11 09:35:11

Puede agregar FrameLayout al fragmento y reemplazarlo con otro fragmento cuando se inicialice.

De esta manera , podrías considerar que el otro fragmento está dentro del primer fragmento.

 3
Author: LoveBigPizza,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-11-03 09:55:29

Use getChildFragmentManager (), siga el enlace : Fragmento anidado

 3
Author: Hacker Celluloid,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-12-23 05:47:32

No hay soporte para MapFragment, el equipo de Android dice que está trabajando en él desde Android 3.0. Aquí más información sobre el tema http://code.google.com/p/android/issues/detail?id=15347&utm_source=buffer&buffer_share=acc72 Pero lo que puedes hacer es crear un Fragmento que devuelva una MapActivity. Aquí hay un ejemplo de código. Gracias a inazaruk: https://github.com/inazaruk/examples/tree/master/MapFragmentExample

Cómo funciona:

- MainFragmentActivity es la actividad que extiende FragmentActivity y aloja dos MapFragments. - MyMapActivity extiende MapActivity y tiene MapView. - LocalActivityManagerFragment hosts LocalActivityManager. - MyMapFragment extiende LocalActivityManagerFragment y con la ayuda de TabHost crea instancia interna de MyMapActivity. si tiene alguna duda por favor hágamelo saber

 1
Author: rallat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-07-12 18:10:21

Curently en fragmento anidado, el anidado uno(s) solo son compatibles si se generan mediante programación! Por lo tanto, en este momento no se admite ningún diseño de fragmento anidado en el esquema de diseño xml.

 1
Author: Andrea Bellitto,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-09-30 07:03:33

No es nada complicado. No podemos usar getFragmentManager () aquí. Para usar Fragmentos dentro de un Fragmento, usamos getChildFragmentManager(). El resto será lo mismo.

 1
Author: Wijay Sharma,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-28 20:09:07

Hola resolví este problema poniendo cada fragmento en un diseño distinto.E hice visible el Diseño relacionado e hice que las otras visibilidades desaparecieran.

Quiero decir:

<?xml version="1.0" encoding="utf-8"?>
 <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:id="@+id/linearLayout1"
           android:layout_width="match_parent"
           android:layout_height="wrap_content"
           android:orientation="horizontal">
           <Button android:layout_width="wrap_content"
                   android:id="@+id/button1"
                   android:layout_height="wrap_content"
                   android:text="Button1"></Button>
           <Button android:text="Button2"
                   android:id="@+id/button2"
                   android:layout_width="wrap_content"
                   android:layout_height="wrap_content"></Button>
           <Button android:text="Button3"
                   android:id="@+id/button3"
                   android:layout_width="wrap_content"
                   android:layout_height="wrap_content"></Button>
           <Button android:text="Button4"
                   android:id="@+id/button4"
                   android:layout_width="wrap_content"
                   android:layout_height="wrap_content"></Button>
   </LinearLayout>
   <LinearLayout android:layout_width="full_screen"
              android:layout_height="0dp"
              android:layout_weight="1"
              android:id="action_For_Button1"
              android:visibility="visible">
                    <Fragment android:layout_width="full_screen"
                              android:layout_height="full_screen"
                              android:id="fragment1"
                                        .
                                        .
                                        .
             / >
     </LinearLayout>

     <LinearLayout android:layout_width="full_screen"
              android:layout_height="0dp"
              android:id="action_For_Button1"
              android:layout_weight="1"
              android:visibility="gone">
                       <Fragment android:layout_width="full_screen"
                                 android:layout_height="full_screen"
                                 android:id="fragment2"
                                           .
                                           .
                                           .
             / >
        </LinearLayout>
                     .
                     .
                     .
        </LinearLayout>

Asumí que abrirás tu página cuando se haga clic en el botón 1.Puedes controlar las visibilidades de tu fragmento al hacer clic.Puede hacer que el diseño relacionado sea visible y que los demás desaparezcan y por el Administrador de fragmentos puede tomar su fragmento.Este enfoque funcionó para mí.Y desde vista que tiene visibilidad: gone es invisible, y no toma ningún espacio para propósitos de diseño Creo que este enfoque no causa ningún problema de espacio.

P.d.:Acabo de tratar de explicar mi código de solución puede tener errores de sintaxis o estructura incompleta.

 0
Author: Sevil,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-11-26 00:31:58

Que puede ayudar a aquellos que trabajan en Kotlin puede utilizar la función de extensión así que crea un archivo kotlin digamos "util.kt " y añadir este trozo de código

fun Fragment.addChildFragment(fragment: Fragment, frameId: Int) {

    val transaction = childFragmentManager.beginTransaction()
    transaction.replace(frameId, fragment).commit()
}

Digamos que esta es la clase del hijo

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)
        ...
    }
    ...
}

Ahora puedes añadir a los hijos al fragmento del padre así

 FatherPresentation:Fragment()
{
  ...

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

Donde R. id.fragmet_field es el id del layout que contendrá el fragmento.Esta mentira está dentro del fragmento del padre, por supuesto. Aqui es un ejemplo

Padre-Fragmento.xml :

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

    ...

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:id="@+id/fragmet_field"
            android:orientation="vertical"
            >
        </LinearLayout>
    ...

    </LinearLayout>
 0
Author: ZINA TAKLIT,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-16 23:29:42