Join FlipAndroid.COM Telegram Group: https://t.me/joinchat/F_aqThGkhwcLzmI49vKAiw


Fragmentos restauran el estado en la orientación cambiada

Tengo que implementar la navegación de fragmentos "standart" en mi aplicación (ver enlace ).

El problema es cuando el dispositivo está en modo vertical, debería mostrarse sólo 1 fragmento, y cuando se gira a modo horizontal, se deben mostrar 2 fragmentos.

He intentado hacer esto de 2 maneras diferentes:

1) Uso sólo 1 actividad con diferentes diseños de retrato y paisaje.

Diseño vertical xml:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" > <FrameLayout android:id="@+id/main_frame_fragment_container" android:layout_width="match_parent" android:layout_height="match_parent" /> </RelativeLayout> 

Y aquí `s disposición del paisaje:

 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:baselineAligned="false" android:orientation="horizontal" > <FrameLayout android:id="@+id/main_frame_fragment_container_left" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1" /> <FrameLayout android:id="@+id/main_frame_fragment_container_right" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1" /> </LinearLayout> 

Método de onCreate del `s de la actividad:

  private static ItemsFragment mItemsFragment; private static ItemDetailsFragment mItemDetailsFragment; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); if (mItemsFragment == null) { mItemsFragment = ItemsFragment.newInstance(); } if (mItemDetailsFragment == null) { mItemDetailsFragment = ItemDetailsFragment.newInstance(); } if (isLandscape()) { getSupportFragmentManager().beginTransaction().replace(R.id.main_frame_fragment_container_left, mItemsFragment) .commit(); getSupportFragmentManager().beginTransaction() .replace(R.id.main_frame_fragment_container_right, mItemDetailsFragment).commit(); } else { getSupportFragmentManager().beginTransaction().replace(R.id.main_frame_fragment_container, mItemsFragment) .commit(); } } 

Y esa es la forma en que refresco segundo fragmento:

 Bundle bundle = new Bundle(); bundle.putSerializable(BaseFragment.KEY_BUNDLE_ITEM, response.getItem()); mItemDetailsFragment = ItemDetailsFragment.newInstance(bundle); if (isLandscape()) { getSupportFragmentManager().beginTransaction() .replace(R.id.main_frame_fragment_container_right, mItemDetailsFragment).commit(); } else { getSupportFragmentManager().beginTransaction() .replace(R.id.main_frame_fragment_container, mItemDetailsFragment).addToBackStack(null).commit(); } 

También guardo y restauro estados de los fragmentos, así que mis datos no desaparecen después de rotaciones. En general, este código funciona correctamente en mi caso.

2) Utilizo 2 actividades y la misma disposición para modos de la 1ra actividad del retrato y del paisaje.

Xml es el mismo que en el anterior para el paisaje:

  <FrameLayout android:id="@+id/main_frame_fragment_container_left" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1" /> <FrameLayout android:id="@+id/main_frame_fragment_container_right" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1" /> </LinearLayout> 

OnCreate método (nota, que las entidades fragmentos no son estáticos, como lo fue en el primer caso): private ItemsFragment mItemsFragment; Private ItemDetailsFragment mItemDetailsFragment;

 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); if (savedInstanceState == null) { mItemsFragment = ItemsFragment.newInstance(); mItemDetailsFragment = ItemDetailsFragment.newInstance(); getSupportFragmentManager().beginTransaction().replace(R.id.main_frame_fragment_container_left, mItemsFragment) .commit(); getSupportFragmentManager().beginTransaction() .replace(R.id.main_frame_fragment_container_right, mItemDetailsFragment).commit(); } } 

Y ahora si el dispositivo está en el modo de retrato, comienzo nuevo Actividad:

 if (isLandscape()) { Bundle bundle = new Bundle(); bundle.putSerializable(BaseFragment.KEY_BUNDLE_ITEM, response.getItem()); mItemDetailsFragment = ItemDetailsFragment.newInstance(bundle); getSupportFragmentManager().beginTransaction() .replace(R.id.main_frame_fragment_container_right, mItemDetailsFragment).commit(); } else { Intent intent = new Intent(getApplicationContext(), DetailsActivity.class); intent.putExtra(KEY_ITEM, response.getItem()); startActivity(intent); } 

Y, por fin, el método onCreate de 2nd Activity:

 protected void onCreate(Bundle arg0) { super.onCreate(arg0); setContentView(R.layout.activity_details); if (isLandscape()) { finish(); } Item item = (Item) getIntent().getExtras().getSerializable(KEY_ITEM); Bundle bundle = new Bundle(); bundle.putSerializable(BaseFragment.KEY_BUNDLE_ITEM, item); ItemDetailsFragment mItemDetailsFragment = ItemDetailsFragment.newInstance(bundle); getSupportFragmentManager().beginTransaction() .replace(R.id.main_frame_fragment_container, mItemDetailsFragment).commit(); } 

Cuando el dispositivo se gira al modo horizontal, termina la 2ª actividad y veo mi primera actividad con 2 fragmentos (como se esperaba).

Pregunta:

En el primer caso guardo fragmentos como variables estáticas, y debido a esto no me importa si cambio 2º estado de fragmento en modos vertical o horizontal (se usa el mismo fragmento). Pero no creo que sea una buena idea guardarlo como campos estáticos.

En el segundo caso no sé cómo sincronizar la Actividad A Fragmento B (paisaje) y Actividad B Fragmento B (retrato). Si cambio algo en el fragmento (quiero decir, botón de conmutación, etc) y girar el dispositivo, los cambios deben aplicarse en otro fragmento.

En general, ¿qué caso es mejor, y si segundo, ¿cómo puedo resolver el problema de sincronización? O tal vez hay otra manera más fácil. Gracias por leer, espero que me puedan ayudar 🙂

FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.