Replace () no funciona correctamente con multi-fragmentos

Actividad principal

package example.antonio.activitydemo; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Button; import android.support.v4.app.*; public class MainActivity extends FragmentActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); final FragmentManager fragmentManager = getSupportFragmentManager(); Button button = (Button) findViewById(R.id.button); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { FirstFragment fragment = new FirstFragment(); FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); fragmentTransaction.add(R.id.container, fragment); fragmentTransaction.commit(); } }); Button button2 = (Button) findViewById(R.id.button2); button2.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { SecondFragment fragment = new SecondFragment(); FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); fragmentTransaction.replace(R.id.container, fragment); fragmentTransaction.commit(); } }); } } 

Primer fragmento

 package example.antonio.activitydemo; import android.support.v4.app.Fragment; import android.os.Bundle; import android.view.LayoutInflater; import android.view.ViewGroup; import android.view.View; public class FirstFragment extends Fragment { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInsanceState) { return inflater.inflate(R.layout.first_fragment, container, false); } } 

Segundo fragmento

 package example.antonio.activitydemo; import android.support.v4.app.Fragment; import android.os.Bundle; import android.view.LayoutInflater; import android.view.ViewGroup; import android.view.View; public class SecondFragment extends Fragment { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInsanceState) { return inflater.inflate(R.layout.second_fragment, container, false); } } 

Sus archivos XML:

Main_activity.xml

 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/container" android:orientation="vertical"> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Start1" android:id="@+id/button"/> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Start2" android:id="@+id/button2"/> </LinearLayout> 

First_fragment.xml

 <?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="#000000"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="First!" android:textColor="#ffffff"/> </FrameLayout> 

Second_fragment.xml igual que el anterior, solo con android:text="Second!"

Aquí está la cosa extraña, cuando hago clic para 4 veces el botón de Start1 entonces consigo 4 veces la palabra First! , Hasta aquí todo normal. Siguiendo si Start2 botón Start2 lo que esperaría es el borrado de los 4 fragmentos anteriores y el agregado de solo uno nuevo, con apariencia de Second! . Esto es lo que entendí de los documentos:

Reemplazar un fragmento existente que se agregó a un contenedor. Esto es esencialmente lo mismo que llamar a remove (Fragment) para todos los fragmentos agregados actualmente que se agregaron con el mismo containerViewId y luego agregar (int, Fragment, String) con los mismos argumentos que se dan aquí.

Pero esto es lo que obtengo:

Después de hacer clic 4 veces <code> Start1 </ code> Después de hacer clic en el botón <code> Start2 </ code>

Traté de leer el código fuente, tal vez me encontré donde está el "problema", me gustaría saber lo que piensa y si soy yo que estoy cometiendo un error en alguna parte.

Aquí está el fragmento de BackStackRecord.java , método run() :

 case OP_REPLACE: { Fragment f = op.fragment; int containerId = f.mContainerId; if (mManager.mAdded != null) { for (int i = 0; i < mManager.mAdded.size(); i++) { Fragment old = mManager.mAdded.get(i); if (FragmentManagerImpl.DEBUG) { Log.v(TAG, "OP_REPLACE: adding=" + f + " old=" + old); } if (old.mContainerId == containerId) { if (old == f) { op.fragment = f = null; } else { if (op.removed == null) { op.removed = new ArrayList<Fragment>(); } op.removed.add(old); old.mNextAnim = op.exitAnim; if (mAddToBackStack) { old.mBackStackNesting += 1; if (FragmentManagerImpl.DEBUG) { Log.v(TAG, "Bump nesting of " + old + " to " + old.mBackStackNesting); } } mManager.removeFragment(old, mTransition, mTransitionStyle); } } } } 

Y aquí está el fragmento de FragmentManager.java :

 public void removeFragment(Fragment fragment, int transition, int transitionStyle) { if (DEBUG) Log.v(TAG, "remove: " + fragment + " nesting=" + fragment.mBackStackNesting); final boolean inactive = !fragment.isInBackStack(); if (!fragment.mDetached || inactive) { if (false) { // Would be nice to catch a bad remove here, but we need // time to test this to make sure we aren't crashes cases // where it is not a problem. if (!mAdded.contains(fragment)) { throw new IllegalStateException("Fragment not added: " + fragment); } } **if (mAdded != null) { mAdded.remove(fragment); }** if (fragment.mHasMenu && fragment.mMenuVisible) { mNeedMenuInvalidate = true; } fragment.mAdded = false; fragment.mRemoving = true; moveToState(fragment, inactive ? Fragment.INITIALIZING : Fragment.CREATED, transition, transitionStyle, false); } } 

Como se puede ver, el método removeFragment elimina un fragmento de mAdded pero después en el método run() , el índice i no se modifica, se reinicia desde donde se ha dejado, de tal manera que puede perder algunos elementos …

No se puede lograr este escenario con el lineallayout como un contenedor.

Si intenta usar el fragmento como un contenedor en linearlayout puede lograrlo. Por favor remítase a este enlace para más aclaraciones

Android: el fragmento .replace () no reemplaza el contenido: lo pone en la parte superior

De lo contrario, utilice el siguiente código para las acciones de clic de botón,

 Button button = (Button) findViewById(R.id.button); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { FirstFragment fragment = new FirstFragment(); FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction(); fragmentTransaction.add(R.id.container, fragment).addToBackStack(null); fragmentTransaction.commit(); } }); Button button2 = (Button) findViewById(R.id.button2); button2.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { SecondFragment fragment = new SecondFragment(); FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); for(int i=0; i < getSupportFragmentManager().getBackStackEntryCount(); i++) getSupportFragmentManager().popBackStack(); fragmentTransaction.replace(R.id.container, fragment); fragmentTransaction.commit(); } }); 

Espero que esto te ayude .. Gracias

  • Android Studio - ProGuard "java.io.IOException ... bin \ classes (Ningún archivo o directorio)"
  • Referencia débil en lugar de getActivity () (evitar Android memoria fugas)?
  • Triangulación Tutoriales para Android
  • ¿Cómo puedo recuperar el tamaño de un archivo durante la descarga de una URL (mediante una conexión http)?
  • Cómo limitar el tamaño del archivo en Java
  • Android AccountManager lanza AuthenticatorException: falla de enlace al agregar cuenta
  • ¿Cómo se puede convertir mejor StringBuilder en String ?
  • ¿Puedo hacer referencia al botón de OnClickListener desde dentro del listener? (androide)
  • Cambiar la conectividad de Android con Robolectric
  • java.lang.VerifyError: com / crashlytics / android / core / CrashlyticsCore
  • Cómo convertir una dirección MAC a un Hex y pasarlo a un bytearray en java
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.