Manejar la duplicación de fragmentos en la pantalla Girar (con código de ejemplo)
Hay algunas respuestas similares, pero no a esta situación.
Mi situación es simple.
Tengo una actividad con dos diseños diferentes, uno en retrato y otro en paisaje.
EnRetrato, yo suelo<FrameLayout>
y añadirFragment
en ellodinamicamente.
EnPaisaje, yo suelo<fragment>
entonces elFragment
esestático. (de hecho esto no importa)
Primero comienza enRetrato, luego agregué elFragment
por simplemente:
ListFrag listFrag = new ListFrag();
getSupportFragmentManager().beginTransaction()
.replace(R.id.FragmentContainer, listFrag).commit();
dóndeListFrag extends ListFragment
.
Luego hago un giro de pantalla.Encontré que listFrag se está recreando en el modo horizontal. (En el cual noté laonCreate()
método se llama de nuevo con un paquete no nulo)
Traté de usarsetRetainInstance(false)
como dijo @NPike enesta publicación. Pero elgetRetainInstance()
ya estáfalse
por defecto. No hace lo que esperaba comolos docs dijo. ¿Podría alguien explicar por favor?
El fragmento con el que estoy tratando es unListFragment
que hacesetListAdapter()
enonCreate()
. Entonces elif (container == null) return null;
método no se puede utilizar aquí. (o no se como aplicar).
Tengo algunos consejos deesta publicación. Debo usarif (bundle != null) setListAdapter(null); else setListAdapter(new ...);
en miListFragment
? Pero, ¿existe una forma más agradable de eliminar / eliminar el fragmento cuando se destruye / se separa, en lugar de hacerlo en su momento de creación? (así como elif (container == null) return null;
método)
Editar:
La única forma limpia que encontré es haciendogetSupportFragmentManager().beginTransaction().remove(getSupportFragmentManager().findFragmentById(R.id.FragmentContainer)).commit();
enonSaveInstanceState()
. Pero planteará otros problemas.
Cuando la pantalla está parcialmente oculta, como los cuadros de diálogo WhatsApp o TXT aparecen, el fragmento también desaparecerá.(Esto es relativamente menor, solo problema visual)
Cuando la pantalla gira, la Actividad se destruye completamente y se vuelve a crear. Así que puedo volver a agregar el fragmento enonCreate(Bundle)
oonRestoreInstanceState(Bundle)
. Pero en el caso de (1), así como las actividades de cambio, tampocoonCreate(Bundle)
nionRestoreInstanceState(Bundle)
se llamará cuando el usuario vuelva a mi actividad. No tengo dónde recrear la Actividad (y recuperar datos de Bundle).
Lo siento, no lo dije claramente, ya tengo una decisión, que elgetSupportFragmentManager()...replace(...).commit();
La línea solo se ejecuta en modo vertical.
He extraído el código simple, para una mejor ilustración de la situación :)
MainActivity.java
package com.example.fragremovetrial;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
public class MainActivity extends FragmentActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (findViewById(R.id.FragmentContainer) != null) {
System.out.println("-- Portrait --"); // Portrait
ListFrag listFrag = new ListFrag();
getSupportFragmentManager().beginTransaction()
.replace(R.id.FragmentContainer, listFrag).commit();
} else {
System.out.println("-- Landscape --"); // Landscape
}
}
@Override
protected void onResume() {
super.onResume();
if (findViewById(R.id.FragmentContainer) != null) {
System.out.println("getRetainInstance = " +
getSupportFragmentManager().findFragmentById(R.id.FragmentContainer).getRetainInstance());
}
}
}
layout / activity_main.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/FragmentContainer"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
layout-land / activity_main.xml (no importa)
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
</LinearLayout>
ListFrag.java
package com.example.fragremovetrial;
import android.os.Bundle;
import android.support.v4.app.ListFragment;
import android.widget.ArrayAdapter;
public class ListFrag extends ListFragment {
private String[] MenuItems = { "Content A", "Contnet B" };
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
System.out.println("ListFrag.onCreate(): " + (savedInstanceState == null ? null : savedInstanceState));
setListAdapter(new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, MenuItems));
}
}
Fíjate que tengo lo siguiente
Mensajes de depuración- retrato -
ListFrag.onCreate (): null
getRetainInstance = false
(rotar Puerto -> Tierra)
ListFrag.onCreate (): Bundle [{android: view_state=android.util.SparseArray@4052dd28}]
- Paisaje -
La vista enfocada anteriormente informó el id. 16908298 durante la grabación, pero no se puede encontrar durante la restauración.
(girar tierra -> puerto)
ListFrag.onCreate (): Bundle [{android: view_state=android.util.SparseArray@405166c8}]
- retrato -
ListFrag.onCreate (): null
getRetainInstance = false
(rotar Puerto -> Tierra)
ListFrag.onCreate (): Bundle [{android: view_state=android.util.SparseArray@4050fb40}]
- Paisaje -
La vista enfocada anteriormente informó el id. 16908298 durante la grabación, pero no se puede encontrar durante la restauración.
(girar tierra -> puerto)
ListFrag.onCreate (): Bundle [{android: view_state=android.util.SparseArray@40528c60}]
- retrato -
ListFrag.onCreate (): null
getRetainInstance = false
donde el número de Fragmento creado seráno aumentar infinitamente como pantalla sigue girando, que no puedo explicar. (por favor ayuda)