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.
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()
.
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!
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
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
- La biblioteca de soporte se está utilizando para que los fragmentos anidados se puedan usar antes de Android 4.2.
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();
}
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
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) {
}
}
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.
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
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
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.
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.
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.
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>
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