¿Cómo evito que la barra de estado y la barra de navegación se animen durante una transición de animación de escena de actividad?

En primer lugar, el fondo de mi barra de estado está configurado en marrón oscuro, y el fondo de mi barra de navegación es negro por defecto. Estoy usando el tema Luz material.

Estoy comenzando una nueva actividad usando ActivityOptions.makeSceneTransitionAnimation con transiciones predeterminadas, y noto que tanto el estado como las barras de navegación se desvanecen brevemente a blanco y luego vuelven a los colores correctos.

De acuerdo con la documentación :

Para obtener el efecto completo de una transición, debe habilitar las transiciones de contenido de ventana en las actividades de llamada y llamada. De lo contrario, la actividad de llamada iniciará la transición de salida, pero luego verá una transición de ventana (como escala o fundido)

Estoy usando getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS); en las actividades llamadas y llamadas.

De forma similar, si cambio la transición de entrada a una diapositiva, tanto el estado como las barras de navegación tienen brevemente una transición de diapositiva con un fondo blanco.

¿Cómo evito que la barra de estado y la barra de navegación se animen durante una transición de animación de escena de actividad?

Hay dos enfoques que puede usar para evitar que la barra de navegación / estado se active durante la transición:

Método n. ° 1: excluya la barra de estado y la barra de navegación de la transición predeterminada de salida / entrada de desvanecimiento de la ventana

El motivo por el que la barra de navegación / estado se desvanece durante la transición es porque, de forma predeterminada, todas las vistas no compartidas (incluidos los fondos de navegación / barra de estado) se desvanecerán en sus llamadas / actividades llamadas respectivamente una vez que comience la transición . Sin embargo, puede evitar esto fácilmente excluyendo los fondos de navegación / barra de estado de la ventana predeterminada de salida / entrada de transición de Fade . Simplemente agregue el siguiente código a los métodos onCreate() sus actividades:

 Transition fade = new Fade(); fade.excludeTarget(android.R.id.statusBarBackground, true); fade.excludeTarget(android.R.id.navigationBarBackground, true); getWindow().setExitTransition(fade); getWindow().setEnterTransition(fade); 

Esta transición también podría declararse en el tema de la actividad utilizando XML (es decir, en su propio archivo res/transition/window_fade.xml ):

 < ?xml version="1.0" encoding="utf-8"?>       

Método n. ° 2: agregue la barra de estado y la barra de navegación como elementos compartidos

Este enfoque se basa en la respuesta de klmprt, que casi funcionó para mí … aunque todavía necesitaba hacer un par de modificaciones.

En mi Actividad de llamada, usé el siguiente código para comenzar la Actividad:

 View statusBar = findViewById(android.R.id.statusBarBackground); View navigationBar = findViewById(android.R.id.navigationBarBackground); List> pairs = new ArrayList<>(); if (statusBar != null) { pairs.add(Pair.create(statusBar, Window.STATUS_BAR_BACKGROUND_TRANSITION_NAME)); } if (navigationBar != null) { pairs.add(Pair.create(navigationBar, Window.NAVIGATION_BAR_BACKGROUND_TRANSITION_NAME)); } pairs.add(Pair.create(mSharedElement, mSharedElement.getTransitionName())); Bundle options = ActivityOptions.makeSceneTransitionAnimation(activity, pairs.toArray(new Pair[pairs.size()])).toBundle(); startActivity(new Intent(context, NextActivity.class), options); 

Hasta ahora, esto es esencialmente lo mismo que sugirió klmprt en su respuesta. Sin embargo, también necesité agregar el siguiente código en el método onCreate() Activity llamado para evitar que la barra de estado y la barra de navegación “parpadeen” durante la transición:

 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_next); // Postpone the transition until the window's decor view has // finished its layout. postponeEnterTransition(); final View decor = getWindow().getDecorView(); decor.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { decor.getViewTreeObserver().removeOnPreDrawListener(this); startPostponedEnterTransition(); return true; } }); } 

Agregar la barra de estado y los fondos de la barra de navegación como elementos compartidos los forzará a dibujarse sobre la transición predeterminada de salida / entrada de fundido de la ventana, lo que significa que no se desvanecerán durante la transición. Se puede encontrar más debate sobre este enfoque en esta publicación de Google+ .

Debe compartirlos en ActivityOptions.makeSceneTransitionAnimation.

P.ej:

 ActivityOptions.makeSceneTransitionAnimation(... Pair.create(activity.findViewById(android.R.id.window_status_bar), Window.STATUS_BAR_BACKGROUND_TRANSITION_NAME) 

(disculpe el psuedo; no tengo el valor exacto de android.R.id a mano)

Puede ejecutar una transición apropiada después de haber compartido las vistas.

Evite completamente que las transiciones de actividad interfieran con las transiciones de elementos compartidos:

En la actividad de salida, llame a getWindow (). SetExitTransition (null);

En la actividad de entrada, llame a getWindow (). SetEnterTransition (null);

Desde https://stackoverflow.com/a/34907685/967131

Sospecho que esto puede tener efectos secundarios, pero no estoy seguro. Es muy simple y funciona sin embargo.

Evite que elementos específicos parpadeen:

Empecé con la respuesta de Alex Lockwood e hice un poco de experimentación para intentar que funcionara. El núcleo es correcto, aunque no necesitaba el código que sugiere para la Actividad de recepción, pero me encontré con algunos problemas llamándolo en un Fragmento (en lugar de una Actividad) y configurando una barra de herramientas como la barra de acciones.

Oh, ¿el Fragmento? Vi muchos comentarios de que tratar de recuperar las referencias a la barra de estado y la barra de navegación era nulo. Lo mismo me sucedió a mí también, hasta que me di cuenta de que no los encontraría en el diseño del Fragmento … estaban por encima de ese nivel. Por lo tanto, el código a continuación para obtener la vista de decoración de la Actividad y buscar eso. Entonces los encontré sin ningún problema.

Al final, desarrollé este método de utilidad:

 public static Bundle transitionOptions(Activity activity, int transitionViewResId, int transitionNameResId) { if (VERSION.SDK_INT < VERSION_CODES.LOLLIPOP) { return null; } View decorView = activity.getWindow().getDecorView(); View statusBar = decorView.findViewById(android.R.id.statusBarBackground); View navigationBar = decorView.findViewById(android.R.id.navigationBarBackground); View appBarLayout = decorView.findViewById(**R.id.appbarlayout**); View transitionView = decorView.findViewById(transitionViewResId); String transitionName = activity.getString(transitionNameResId); List> pairs = new ArrayList<>(); pairs.add(Pair.create(statusBar, Window.STATUS_BAR_BACKGROUND_TRANSITION_NAME)); pairs.add(Pair.create(navigationBar, Window.NAVIGATION_BAR_BACKGROUND_TRANSITION_NAME)); if (appBarLayout != null) { pairs.add(Pair.create(appBarLayout, activity.getString(**R.string.transition_appbarlayout**))); } pairs.add(Pair.create(transitionView, transitionName)); //noinspection unchecked - we're not worried about the "unchecked" conversion of List to Pair[] here return ActivityOptionsCompat.makeSceneTransitionAnimation(activity, pairs.toArray(new Pair[pairs.size()])) .toBundle(); } 

Nota R.string.transition_appbarlayout y R.id.appbarlayout . Estas identificaciones son arbitrarias, siempre que coincidan con lo que usa su código. En mi XML, diseño la barra de acción personalizada como tal (editada a lo esencial):

 < ?xml version="1.0" encoding="utf-8"?>    

Si no utiliza una barra de herramientas como esta, esa parte se puede eliminar del método de utilidad.

Entonces lo llamarías en tu Fragmento así:

 startActivity(intent, UIUtils.transitionOptions(getActivity(), R.id.**my_view**, R.string.**transition_my_view**)); 

Utilizando los valores que desee, siempre que coincida con su XML.

Esto evita que la barra de estado, la barra de herramientas y la barra de navegación (botones de atrás / inicio / aplicaciones recientes) parpadeen durante la transición. El rest de la transición de actividad es normal.

En mi caso, nuestro tema de aplicación tiene un android:windowBackground of blue. Esto causa un destello azul en la transición, lo cual es bastante frustrante. Pero en lugar de hacer un cambio que afecte a toda la aplicación de esa manera, por ahora voy con la primera opción, rápida y sucia.

Por lo que yo entiendo, esto es causado por la superposición de transición de actividad. Para superar este problema, he utilizado los siguientes valores en los métodos onCreate() de ambas actividades:

 getWindow().setAllowEnterTransitionOverlap(false); getWindow().setAllowReturnTransitionOverlap(false); 

Acabo de tener este mismo problema, y ​​parece que las respuestas carecen de una pieza crítica para el rompecabezas. Recuerde que en una transición de elemento compartido, todo sucede en la Actividad de destino .

Para eliminar el efecto de parpadeo, simplemente agregue lo siguiente a la actividad que se está llamando:

 Fade fade = new Fade(); fade.excludeTarget(android.R.id.statusBarBackground, true); fade.excludeTarget(android.R.id.navigationBarBackground, true); getWindow().setEnterTransition(fade); getWindow().setExitTransition(fade); 

¡Esto debería solucionar tu problema!

Así es como lo hice. Comparto tanto la Status Bar como la Navigation Bar en SharedElementTransition junto con un ImageView :

 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { View imageView = view.findViewById(R.id.iv); Resources resources = view.getResources(); imageView.setTransitionName(resources.getString(R.string.transition_image_thumbnail)); Pair p1 = Pair.create(imageView, resources.getString(R.string.transition_image_thumbnail)); Window window = getActivity().getWindow(); View navigationBar = getActivity().findViewById(android.R.id.navigationBarBackground); View statusBar = getActivity().findViewById(android.R.id.statusBarBackground); Pair p2 = Pair.create(statusBar, statusBar.getTransitionName()); Pair p3 = Pair.create(navigationBar, navigationBar.getTransitionName()); ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation(getActivity(), p1, p2, p3); ActivityCompat.startActivity(getActivity(), intent, options.toBundle()); } else { startActivity(intent); } 

getWindow().setEnterTransition(null); en la transición de entrada eliminó la superposición blanca para mí.