una - fragment android
Ciclo de vida de Android Fragment sobre cambios de orientaciĆ³n (7)
Usando el paquete de compatibilidad para apuntar 2.2 usando Fragmentos.
Después de recodificar una actividad para usar fragmentos en una aplicación, no pude obtener los cambios de orientación / administración del estado funcionando, así que creé una pequeña aplicación de prueba con una sola FragmentActivity y un solo Fragment.
Los registros de los cambios de orientación son raros, con múltiples llamadas a los fragmentos OnCreateView.
Obviamente me falta algo, como separar el fragmento y volver a colocarlo en lugar de crear una nueva instancia, pero no puedo ver ninguna documentación que indique dónde me estoy equivocando.
¿Alguien puede arrojar algo de luz sobre lo que estoy haciendo mal aquí por favor? Gracias
El registro es el siguiente después de cambios de orientación.
Initial creation
12-04 11:57:15.808: D/FragmentTest.FragmentTestActivity(3143): onCreate
12-04 11:57:15.945: D/FragmentTest.FragmentOne(3143): OnCreateView
12-04 11:57:16.081: D/FragmentTest.FragmentOne(3143): OnCreateView->SavedInstanceState null
Orientation Change 1
12-04 11:57:39.031: D/FragmentTest.FragmentOne(3143): onSaveInstanceState
12-04 11:57:39.031: D/FragmentTest.FragmentTestActivity(3143): onCreate
12-04 11:57:39.031: D/FragmentTest.FragmentOne(3143): OnCreateView
12-04 11:57:39.031: D/FragmentTest.FragmentOne(3143): OnCreateView->SavedInstanceState not null
12-04 11:57:39.031: D/FragmentTest.FragmentOne(3143): OnCreateView
12-04 11:57:39.167: D/FragmentTest.FragmentOne(3143): OnCreateView->SavedInstanceState null
Orientation Change 2
12-04 11:58:32.162: D/FragmentTest.FragmentOne(3143): onSaveInstanceState
12-04 11:58:32.162: D/FragmentTest.FragmentOne(3143): onSaveInstanceState
12-04 11:58:32.361: D/FragmentTest.FragmentTestActivity(3143): onCreate
12-04 11:58:32.361: D/FragmentTest.FragmentOne(3143): OnCreateView
12-04 11:58:32.361: D/FragmentTest.FragmentOne(3143): OnCreateView->SavedInstanceState not null
12-04 11:58:32.361: D/FragmentTest.FragmentOne(3143): OnCreateView
12-04 11:58:32.361: D/FragmentTest.FragmentOne(3143): OnCreateView->SavedInstanceState not null
12-04 11:58:32.498: D/FragmentTest.FragmentOne(3143): OnCreateView
12-04 11:58:32.498: D/FragmentTest.FragmentOne(3143): OnCreateView->SavedInstanceState null
Actividad principal (FragmentActivity)
public class FragmentTestActivity extends FragmentActivity {
/** Called when the activity is first created. */
private static final String TAG = "FragmentTest.FragmentTestActivity";
FragmentManager mFragmentManager;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Log.d(TAG, "onCreate");
mFragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();
FragmentOne fragment = new FragmentOne();
fragmentTransaction.add(R.id.fragment_container, fragment);
fragmentTransaction.commit();
}
Y el fragmento
public class FragmentOne extends Fragment {
private static final String TAG = "FragmentTest.FragmentOne";
EditText mEditText;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Log.d(TAG, "OnCreateView");
View v = inflater.inflate(R.layout.fragmentonelayout, container, false);
// Retrieve the text editor, and restore the last saved state if needed.
mEditText = (EditText)v.findViewById(R.id.editText1);
if (savedInstanceState != null) {
Log.d(TAG, "OnCreateView->SavedInstanceState not null");
mEditText.setText(savedInstanceState.getCharSequence("text"));
}
else {
Log.d(TAG,"OnCreateView->SavedInstanceState null");
}
return v;
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
Log.d(TAG, "FragmentOne.onSaveInstanceState");
// Remember the current text, to restore if we later restart.
outState.putCharSequence("text", mEditText.getText());
}
Manifiesto
<uses-sdk android:minSdkVersion="8" />
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<activity
android:label="@string/app_name"
android:name=".activities.FragmentTestActivity"
android:configChanges="orientation">
<intent-filter >
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
El método de su actividad onCreate () se llama después de que la orientación cambie como lo ha visto. Por lo tanto, no ejecutes FragmentTransaction que agrega el Fragment después de que la orientación cambie en tu actividad.
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState==null) {
//do your stuff
}
}
Los fragmentos deben y no deben cambiarse.
En el cambio de configuración, el marco creará una nueva instancia del fragmento para usted y lo agregará a la actividad. Entonces en vez de esto:
FragmentOne fragment = new FragmentOne();
fragmentTransaction.add(R.id.fragment_container, fragment);
hacer esto:
if (mFragmentManager.findFragmentByTag(FRAG1_TAG) == null) {
FragmentOne fragment = new FragmentOne();
fragmentTransaction.add(R.id.fragment_container, fragment, FRAG1_TAG);
}
Tenga en cuenta que el framework agrega una nueva instancia de FragmentOne en el cambio de orientación a menos que llame a setRetainInstance (true), en cuyo caso agregará la instancia anterior de FragmentOne.
Estás superponiendo tus Fragmentos uno encima del otro.
Cuando se produce un cambio de configuración, el Fragmento anterior se agrega a la nueva Actividad cuando se recrea. Este es un dolor masivo en la parte posterior la mayor parte del tiempo.
Puede detener la aparición de errores utilizando el mismo Fragmento en lugar de volver a crear uno nuevo. Simplemente agrega este código:
if (savedInstanceState == null) {
// only create fragment if activity is started for the first time
mFragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();
FragmentOne fragment = new FragmentOne();
fragmentTransaction.add(R.id.fragment_container, fragment);
fragmentTransaction.commit();
} else {
// do nothing - fragment is recreated automatically
}
Sin embargo, ten en cuenta que los problemas se producirán si intentas acceder a Vistas de actividad desde el interior del Fragmento, ya que los ciclos de vida cambiarán sutilmente. (Obtener vistas de una Actividad principal desde un Fragmento no es fácil).
Para citar este libro , "para garantizar una experiencia de usuario coherente, Android persiste en el diseño del Fragmento y la pila posterior asociada cuando se reinicia una Actividad debido a un cambio de configuración". (p 124)
Y la forma de abordar esto es verificar primero si la pila de Fragmentos ya se ha rellenado, y crear la nueva instancia de fragmentos solo si no:
@Override
public void onCreate(Bundle savedInstanceState) {
...
FragmentOne fragment = (FragmentOne) mFragmentManager.findFragmentById(R.id.fragment_container);
if (fragment == null) {
FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();
fragmentTransaction.add(R.id.fragment_container, new FragmentOne());
fragmentTransaction.commit();
}
}
Puede @Override
FragmentActivity usando onSaveInstanceState()
. Asegúrese de no llamar al super.onSaveInstanceState()
en el método.
Si acaba de hacer un proyecto, entonces el gerente del proyecto dice que necesita lograr la pantalla de función de conmutación, pero no desea que la pantalla cambie el diseño de carga diferente (puede crear el diseño y el sistema de diseño de puerto).
Determinará automáticamente el estado de la pantalla, cargará el diseño correspondiente), debido a la necesidad de reiniciar la actividad o fragmento, la experiencia del usuario no es buena, no está directamente en el cambio de pantalla, me refiero? Url = YgNfP-vHy-Nuldi7YHTfNet3AtLdN-w__O3z1wLOnzr3wDjYo7X7PYdNyhw8R24ZE22xiKnydni7R0r35s2fOLcHOiLGYT9Qh_fjqtytJki & wd = & eqid = f258719e0001f24000000004585a1082
La premisa es que su diseño utilice el peso del diseño de layout_weight, de la siguiente manera:
<LinearLayout
Android:id= "@+id/toplayout"
Android:layout_width= "match_parent"
Android:layout_height= "match_parent"
Android:layout_weight= "2"
Android:orientation= "horizontal" >
Así que mi enfoque es que, al cambiar de pantalla, no es necesario cargar un nuevo diseño del archivo de vista, modifique el diseño en onConfigurationChanged pesos dinámicos, los siguientes pasos: 1 primer conjunto: AndroidManifest.xml en el atributo de actividad: android: configChanges = "keyboardHidden | orientation | screenSize" Para evitar el cambio de pantalla, evite volver a cargar, a fin de poder monitorear en onConfigurationChanged 2 la actividad o fragmento de reescritura en el método onConfigurationChanged.
@Override
Public void onConfigurationChanged (Configuration newConfig) {
Super.onConfigurationChanged (newConfig);
SetContentView (R.layout.activity_main);
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
//On the layout / / weight adjustment
LinearLayout toplayout = (LinearLayout) findViewById (R.id.toplayout);
LinearLayout.LayoutParams LP = new LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, 0, 2.0f);
Toplayout.setLayoutParams (LP);
LinearLayout tradespace_layout = (LinearLayout) findViewById(R.id.tradespace_layout);
LinearLayout.LayoutParams LP3 = new LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, 0, 2.8f);
Tradespace_layout.setLayoutParams (LP3);
}
else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT)
{
//On the layout / / weight adjustment
LinearLayout toplayout = (LinearLayout) findViewById (R.id.toplayout);
LinearLayout.LayoutParams LP = new LayoutParams (LinearLayout.LayoutParams.MATCH_PARENT, 0, 2.8f);
Toplayout.setLayoutParams (LP);
LinearLayout tradespace_layout = (LinearLayout) findViewById (R.id.tradespace_layout);
LinearLayout.LayoutParams LP3 = new LayoutParams (LinearLayout.LayoutParams.MATCH_PARENT, 0, 2.0f);
Tradespace_layout.setLayoutParams (LP3);
}
}
Siempre debemos tratar de evitar la excepción de nullpointer, por lo que primero debemos verificar en el método de instancia de guardado la información del paquete. para una breve explicación para verificar este link blog
public static class DetailsActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getResources().getConfiguration().orientation
== Configuration.ORIENTATION_LANDSCAPE) {
// If the screen is now in landscape mode, we can show the
// dialog in-line with the list so we don''t need this activity.
finish();
return;
}
if (savedInstanceState == null) {
// During initial setup, plug in the details fragment.
DetailsFragment details = new DetailsFragment();
details.setArguments(getIntent().getExtras());
getFragmentManager().beginTransaction().add(android.R.id.content, details).commit();
}
}
}