studio provide activity android android-activity android-actionbar up-button

activity - provide back navigation android



Regresar de una actividad usando navigateUpFromSameTask() (4)

En lugar de llamar a NavUtils.navigateUpFromSameTask

Puede obtener el intento de los padres y modificarlo antes de navegar. Por ejemplo:

Intent intent = NavUtils.getParentActivityIntent(this); intent.putExtra("CustInfo", m_custInfo); // CustInfo is serializable NavUtils.navigateUpTo(this, intent);

Esto se comportará exactamente igual que NavUtils.navigateUpFromSameTask pero le permitirá agregar algunas propiedades adicionales a la intención. Puede echarle un vistazo al código de NavUtils.navigateUpFromSameTask , es muy simple.

public static void navigateUpFromSameTask(Activity sourceActivity) { Intent upIntent = getParentActivityIntent(sourceActivity); if (upIntent == null) { throw new IllegalArgumentException("Activity " + sourceActivity.getClass().getSimpleName() + " does not have a parent activity name specified." + " (Did you forget to add the android.support.PARENT_ACTIVITY <meta-data> " + " element in your manifest?)"); } navigateUpTo(sourceActivity, upIntent); }

Hacer que la actividad principal SINGLE_TOP funcione para algunas aplicaciones simples, pero ¿qué pasa si esta actividad no se inició directamente desde su padre? O puede legítimamente querer que el padre exista en varios lugares en la pila de respaldo.

Tengo dos actividades, A y B. Cuando la actividad A se inicia por primera vez, accede al Intent pasado (porque el Bundle es null , como debería ser la primera vez), y muestra la información en consecuencia:

CustInfo m_custInfo; ... protected void onCreate(Bundle savedInstanceState) { ... Bundle bundle = (savedInstanceState == null) ? getIntent().getExtras() : savedInstanceState; m_custInfo = (CustInfo) m_bundle.getSerializable("CustInfo"); if (m_custInfo != null ... }

Esto funciona bien la primera vez. Los controles EditText y ListView se completan correctamente.

Ahora, cuando se hace clic en un elemento de la lista, la actividad B se inicia para mostrar los detalles:

m_custInfo = m_arrCustomers.get(pos); Intent intent = new Intent(A.this, B.class); intent.putExtra("CustInfo", m_custInfo); // CustInfo is serializable // printing this intent, it shows to have extras and no flags startActivityForResult(intent, 1);

Justo antes de que se inicie la actividad B, el marco de trabajo llama a A anulado onSaveInstanceState() :

protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putSerializable("CustInfo", m_custInfo); }

En la actividad B, cuando se presiona el botón Arriba en la barra de acción, quiero volver a la actividad A y mantenerla en el mismo estado que antes:

public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId() == android.R.id.home) { Intent intent = NavUtils.getParentActivityIntent(this); // printing this intent, it shows to have flags but no extras NavUtils.navigateUpFromSameTask(this); // tried finish() here but that created an even bigger mess return true; } ... }

Aquí radica el problema, cuando en onCreate() de la actividad A por segunda vez, el parámetro Bundle es null y getExtras() devuelve null . Desde que se onSaveInstanceState() , esperaba que el parámetro Bundle no fuera null .

He leído sobre este tema en otros sitios web, he intentado con las sugerencias, pero nada funciona.


Esto sucede porque NavUtils.navigateUpFromSameTask() básicamente solo llama a startActivity(intentForActivityA) . Si la actividad A usa el android:launchMode="standard" predeterminado android:launchMode="standard" , se crea una nueva instancia de la actividad y no se utiliza el estado guardado. Hay tres formas de arreglar esto, con varias ventajas y desventajas.

Opción 1

getParentActivityIntent() en la actividad B y especifique los extras apropiados que necesita la actividad A:

@Override public Intent getParentActivityIntent() { Intent intent = super.getParentActivityIntent(); intent.putSerializable("CustInfo", m_custInfo); return intent; }

Nota: Si está utilizando ActionBarActivity y la barra de herramientas de la biblioteca de soporte, deberá reemplazar a getSupportParentActivityIntent() .

Siento que esta es la solución más elegante ya que funciona independientemente de cómo el usuario navegó a la actividad B. Las dos opciones enumeradas a continuación no funcionan correctamente si el usuario navega directamente a la actividad B sin pasar por la actividad A, por ejemplo, si la actividad B se inicia desde una notificación o manejador de URL. Creo que este escenario es la razón por la cual la API de navegación ''hacia arriba'' es complicada y no solo actúa como un tonto botón de retroceso.

Una desventaja de esta solución es que se utiliza la animación de transición de inicio-actividad-estándar estándar en lugar de la animación de la actividad de retorno a la actividad anterior.

opcion 2

Intercepta el botón up y onNavigateUp() como un botón mudo al anular onNavigateUp() :

@Override public boolean onNavigateUp() { onBackPressed(); return true; }

Nota: Si está utilizando ActionBarActivity y la barra de herramientas de la biblioteca de soporte, tendrá que reemplazar onSupportNavigateUp() lugar.

Esta solución es un poco hacky y solo funciona para aplicaciones donde "arriba" y "atrás" deberían comportarse de la misma manera. Esto es probablemente raro, porque si "arriba" y "atrás" deberían comportarse de la misma manera, ¿por qué molestarse en tener un botón de subida? Una de las ventajas de esta solución es que se utiliza la animación estándar de retorno a la actividad previa.

Opción 3

Como lo sugirió yonojoy, configure android:launchMode="singleTop" en la actividad A. Consulte su respuesta para obtener detalles. Tenga en cuenta que singleTop no es apropiado para todas las aplicaciones. Tendrás que probarlo y / o pasar un tiempo leyendo la documentación para decidir por ti mismo.


Mencionas:

En la actividad B, cuando se presiona el botón Arriba en la barra de acción, quiero volver a la actividad A y mantenerla en el mismo estado que antes.

Si su contenido en la Actividad A reside en un Fragmento, llame a setRetainInstance (verdadero) en el onCreate () del Fragmento.

Luego, la instancia de Fragmento se mantendrá en Recreación de la actividad.


Si desea que su aplicación reaccione de esta manera, debe declarar el modo de inicio de su actividad A como:

android:launchMode="singleTop"

en su AndroidManifest.xml.

De lo contrario, Android utiliza el modo de lanzamiento estándar, lo que significa

"El sistema siempre crea una nueva instancia de la actividad en la tarea objetivo"

y su actividad se recrea (consulte la documentación de Android ).

Con singleTop, el sistema regresa a su actividad existente (con el extra original), si está en la parte superior de la pila posterior de la tarea. No es necesario implementar onSaveInstanceState en esta situación.

savedInstanceState es nulo en su caso, porque su actividad no estaba siendo cerrada previamente por el sistema operativo.

Aviso (gracias, desarrollador de Android por señalar this ) :

Si bien esta es una solución a la pregunta, no funcionará si la actividad a la que regresa no está en la parte superior de la pila posterior. Considere el caso de la actividad A que comienza B, que inicia C, y la actividad principal de C está configurada como A. Si llama a NavigateUpFromSameTask() desde C, la actividad se volverá a crear, porque A no está en la parte superior de la pila.

En este caso, uno puede usar este fragmento de código:

Intent intent = NavUtils.getParentActivityIntent(this); intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_SINGLE_TOP); NavUtils.navigateUpTo(this, intent);