support library last example android android-support-library android-5.0-lollipop onactivityresult android-transitions

android - library - Iniciar la actividad desde el fragmento utilizando Transición(compatibilidad con API 21)



implementation android support v4 (4)

Estoy tratando de transferir una aplicación de Android a la nueva biblioteca de soporte (support-v4: 21.0.0) y tengo problemas para iniciar Actividades desde Fragmentos con una transición.

En mis Actividades, he estado haciendo algo como:

Bundle options = ActivityOptionsCompat.makeSceneTransitionAnimation(this).toBundle(); ActivityCompat.startActivityForResult(this, intent, REQUEST_SOMETHING, options);

que funciona bien para las actividades. Sin embargo, si intento hacer algo similar con Fragmentos, como:

Activity activity = getActivity(); Bundle options = ActivityOptionsCompat.makeSceneTransitionAnimation(activity).toBundle(); ActivityCompat.startActivityForResult(activity, intent, REQUEST_SOMETHING, options);

Resulta que onActivityResult() no se llama para el Fragmento, sino solo para la Actividad que lo contiene. No he encontrado nada en la biblioteca de soporte para pasar el paquete de opciones como un parámetro para startActivityForResult() en un Fragmento real y hacer que vuelva a llamar a onActivityResult() en ese Fragmento. es posible?

La solución más sencilla sería manejar todas las llamadas onActivityResult() en la propia Actividad, pero prefiero no hacerlo porque tengo un montón de posibles Fragmentos que pueden estar recibiendo esa devolución de llamada.

Se agradece la ayuda. ¡Gracias!


El método ActivityCompat#startActivityForResult() es solo un proxy para el startActivityForResult(Intent, Bundle) . Llamar al método desde dentro de una clase de fragmentos no significa que eventualmente se llamará onActivityResult() del Fragment , ya que estoy seguro de que lo descubrió. El marco tiene una forma de saber a partir de qué clase se originó la llamada ... el único comportamiento correcto sería llamar al método onActivityResult() la Activity en este caso.

Parece que la mejor opción sería manejar todo en el método onActivityResult() la actividad como sugeriste en tu publicación.


Lamentablemente, ActivityCompat.startActivityForResult() no funciona bien en Fragments (vea la respuesta de Alex Lockwood). Durante varias semanas me maravillé de cómo Google nunca nos dio un método ActivityCompat equivalente a la implementación de Fragment startActivityForResult() . ¡¿Que estaban pensando?! Pero luego tuve una idea: echemos un vistazo a cómo se implementa realmente el método.

De hecho, startActivityForResult() en Fragment es diferente al de la Actividad (ver here ):

public void startActivityForResult(Intent intent, int requestCode) { if (mActivity == null) { throw new IllegalStateException("Fragment " + this + " not attached to Activity"); } mActivity.startActivityFromFragment(this, intent, requestCode); }

Ahora startActivityFromFragment() tiene este aspecto (ver here ):

public void startActivityFromFragment(Fragment fragment, Intent intent, int requestCode) { if (requestCode == -1) { super.startActivityForResult(intent, -1); return; } if ((requestCode&0xffff0000) != 0) { throw new IllegalArgumentException("Can only use lower 16 bits for requestCode"); } super.startActivityForResult(intent, ((fragment.mIndex + 1) << 16) + (requestCode & 0xffff)); }

Google utiliza un cambio de byte impar en el código de solicitud para asegurarse de que solo se llame después al onActivityResult() del Fragmento de llamada. Ahora, como ActivityCompat no proporciona ningún startActivityFromFragment() , la única opción que queda es implementarlo usted mismo. Se requiere reflexión para acceder al campo privado del paquete mIndex .

public static void startActivityForResult(Fragment fragment, Intent intent, int requestCode, Bundle options) { if (Build.VERSION.SDK_INT >= 16) { if ((requestCode & 0xffff0000) != 0) { throw new IllegalArgumentException("Can only use lower 16 bits" + " for requestCode"); } if (requestCode != -1) { try { Field mIndex = Fragment.class.getDeclaredField("mIndex"); mIndex.setAccessible(true); requestCode = ((mIndex.getInt(this) + 1) << 16) + (requestCode & 0xffff); } catch (NoSuchFieldException | IllegalAccessException e) { throw new RuntimeException(e); } } ActivityCompat.startActivityForResult(fragment.getActivity(), intent, requestCode, options); } else { fragment.getActivity().startActivityFromFragment(this, intent, requestCode); } }

Copia ese método donde quieras y úsalo de tu Fragmento. Su onActivityResult() se llamará como debería.

ACTUALIZACIÓN : La biblioteca de soporte v23.2 se lanzó y parece que startActivityFromFragment(Fragment fragment, Intent intent, int requestCode, Bundle options) hace el trabajo ahora :)


Puede crear una interfaz de escucha o simplemente una función pública en su fragmento y pasar los argumentos de los que está obteniendo onActivityResult () de la actividad al oyente o al método público del fragmento y hacer el trabajo deseado allí.


Una forma sencilla:

en Fragmento:

ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation(); this.startActivityFromFragment(this, intent, requestCode, options);