Circular revela transición para una nueva actividad

Según https://developer.android.com/training/material/animations.html

El método ViewAnimationUtils.createCircularReveal() permite animar un círculo de recorte para revelar u ocultar una vista.

Para revelar una vista previamente invisible usando este efecto:

 // previously invisible view View myView = findViewById(R.id.my_view); // get the center for the clipping circle int cx = (myView.getLeft() + myView.getRight()) / 2; int cy = (myView.getTop() + myView.getBottom()) / 2; // get the final radius for the clipping circle int finalRadius = Math.max(myView.getWidth(), myView.getHeight()); // create the animator for this view (the start radius is zero) Animator anim = ViewAnimationUtils.createCircularReveal(myView, cx, cy, 0, finalRadius); // make the view visible and start the animation myView.setVisibility(View.VISIBLE); anim.start(); 

Esto está destinado a revelar una vista. ¿Cómo puedo usar esto para revelar circularmente una actividad completa, sin elementos compartidos?

Específicamente, quisiera que mi searchActivity revelara circularmente del botón de la acción de la búsqueda en la barra de herramientas.

Después de buscar una solución por medio día sin un resultado, me propuse una implementación propia. Estoy usando una actividad transparente con un diseño de raíz coincidente. El diseño raíz es una vista que luego se puede revelar con createCircularReveal() .

Mi código se ve así:

Definición de tema en styles.xml

 <style name="Theme.Transparent" parent="Theme.AppCompat.Light.NoActionBar"> <item name="android:windowIsTranslucent">true</item> <item name="android:statusBarColor">@android:color/transparent</item> <item name="android:windowBackground">@android:color/transparent</item> </style> 

Definición de actividad en AndroidManifest.xml

 <activity android:name=".ui.CircularRevealActivity" android:theme="@style/Theme.Transparent" android:launchMode="singleTask" /> 

Entonces he declarado un diseño para mi actividad (He elegido DrawerLayout, para que pueda tener un NavDrawer. Cada diseño debería funcionar aquí.)

 <android.support.v4.widget.DrawerLayout android:id="@+id/drawer_layout" xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <FrameLayout android:id="@+id/root_layout" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/honey_melon" > <!-- Insert your actual layout here --> </FrameLayout> </android.support.v4.widget.DrawerLayout> 

Importante es FrameLayout con el id root_layout . Esta visión se revelará en la actividad.

Finalmente, implementé CircularRevealActivity y onCreate() :

 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); overridePendingTransition(R.anim.do_not_move, R.anim.do_not_move); setContentView(R.layout.activity_reveal_circular); if (savedInstanceState == null) { rootLayout.setVisibility(View.INVISIBLE); ViewTreeObserver viewTreeObserver = rootLayout.getViewTreeObserver(); if (viewTreeObserver.isAlive()) { viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { circularRevealActivity(); if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) { rootLayout.getViewTreeObserver().removeGlobalOnLayoutListener(this); } else { rootLayout.getViewTreeObserver().removeOnGlobalLayoutListener(this); } } }); } } } 

Era importante poner circularRevealActivity() en un OnGlobalLayoutListener , porque la vista necesita ser dibujada para la animación.

circularRevealActivity() parece la propuesta de Ishaan:

 private void circularRevealActivity() { int cx = rootLayout.getWidth() / 2; int cy = rootLayout.getHeight() / 2; float finalRadius = Math.max(rootLayout.getWidth(), rootLayout.getHeight()); // create the animator for this view (the start radius is zero) Animator circularReveal = ViewAnimationUtils.createCircularReveal(rootLayout, cx, cy, 0, finalRadius); circularReveal.setDuration(1000); // make the view visible and start the animation rootLayout.setVisibility(View.VISIBLE); circularReveal.start(); } 

Editar 1

Se ha añadido la definición de R.anim.do_not_move . Sin embargo, debería funcionar sin esa línea también, si su diseño no especifica transiciones predeterminadas para las actividades. Házmelo saber

R.anim.do_not_move:

 <set xmlns:android="http://schemas.android.com/apk/res/android"> <translate android:fromYDelta="0" android:toYDelta="0" android:duration="@android:integer/config_mediumAnimTime" /> </set> 

Para invertir la animación CircularReveal intercambie los argumentos startRadius y endRadius . También necesitará configurar un AnimatorListener y en el método de devolución de llamada onAnimationEnd() es donde puede llamar a finishAfterTransition() . Esto es para cuando presiona la up navigation o haga clic en el back button .

Creo que puede utilizar ActivityOptionsCompat.makeClipRevealAnimation .

[ https://developer.android.com/reference/android/support/v4/app/ActivityOptionsCompat.html#makeClipRevealAnimation(android.view.View , int, int, int, int)] ( https://developer.android .com / reference / android / support / v4 / app / ActividadOptionsCompat.html # makeClipRevealAnimation (android.view.View , int, int, int, int)

Si desea invertir la revelación circular al dejar la actividad, utilice la siguiente modificación en onBackPressed ().

 @Override public void onBackPressed() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { int cx = rootLayout.getWidth(); int cy = 0; float finalRadius = Math.max(rootLayout.getWidth(), rootLayout.getHeight()); Animator circularReveal = ViewAnimationUtils.createCircularReveal(rootLayout, cx, cy, finalRadius, 0); circularReveal.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animator) { } @Override public void onAnimationEnd(Animator animator) { rootLayout.setVisibility(View.INVISIBLE); finish(); } @Override public void onAnimationCancel(Animator animator) { } @Override public void onAnimationRepeat(Animator animator) { } }); circularReveal.setDuration(400); circularReveal.start(); }else{ super.onBackPressed(); } } 

O tienes que dibujar la vista de círculo, y después de eso debes crear una animación a ella.

Creación de la vista de círculo:

 public class Circle extends View { private static final int START_ANGLE_POINT = 90; private final Paint paint; private final RectF rect; private float angle; public Circle(Context context, AttributeSet attrs) { super(context, attrs); final int strokeWidth = 40; paint = new Paint(); paint.setAntiAlias(true); paint.setStyle(Paint.Style.STROKE); paint.setStrokeWidth(strokeWidth); //Circle color paint.setColor(Color.RED); //size 200x200 example rect = new RectF(strokeWidth, strokeWidth, 200 + strokeWidth, 200 + strokeWidth); //Initial Angle (optional, it can be zero) angle = 120; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.drawArc(rect, START_ANGLE_POINT, angle, false, paint); } public float getAngle() { return angle; } public void setAngle(float angle) { this.angle = angle; } } 

Creación de la clase de animación para establecer el nuevo ángulo:

 public class CircleAngleAnimation extends Animation { private Circle circle; private float oldAngle; private float newAngle; public CircleAngleAnimation(Circle circle, int newAngle) { this.oldAngle = circle.getAngle(); this.newAngle = newAngle; this.circle = circle; } @Override protected void applyTransformation(float interpolatedTime, Transformation transformation) { float angle = oldAngle + ((newAngle - oldAngle) * interpolatedTime); circle.setAngle(angle); circle.requestLayout(); } } 

Ponga el círculo en su diseño:

 <com.package.Circle android:id="@+id/circle" android:layout_width="300dp" android:layout_height="300dp" /> 

Y, finalmente, iniciar la animación:

 Circle circle = (Circle) findViewById(R.id.circle); CircleAngleAnimation animation = new CircleAngleAnimation(circle, 240); animation.setDuration(1000); circle.startAnimation(animation); 
  • ¿Cómo puedo eliminar el relleno superior innecesario de la vista de navegación?
  • Cómo crear una barra de herramientas de la tarjeta usando appcompat v7
  • Desactivar la hamburguesa para animar la flecha hacia atrás en la barra de herramientas
  • Comunicación entre las pestañas de SlidingTabLayout
  • Material Tema Android Action Bar Estilo Generador
  • Efecto de ondulación en la barra de herramientas cortada
  • ¿Cómo mantener la barra de herramientas fija en la parte superior cuando AppBar colapsa / se expande?
  • Animar la vista de redimensionamiento en el diseño del material
  • Android RecyclerView con indicador de progreso y animación
  • No hay efecto de ondulación en el tacto en la vista de reciclaje
  • Último elemento de ListView: Fab lo oculta
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.