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.
- ¿Cómo habilitar o falsificar la mini variante de la guía de diseño de materiales para android.support.v4.widget.DrawerLayout?
- Biblioteca de soporte de diseño de materiales
- Fragmento de error: tipos incompatibles, requiere android.app.fragment pero encontró activity.messagefragment
- Cómo implementar Material Design "Full-width text field"?
- Animación de material para Android con pantalla Splash como aplicación de Palabre
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.
- Error: (2, 0) Plugin con id 'com.github.dcendents.android-maven' no encontrado
- Android Material diseño transiciones
- ¿Qué hace TranslationZ realmente en Android?
- Centro de la pestaña activa dentro de TabLayout
- ¿Cómo obtener las preferencias del sistema Android?
- No se encontró ningún recurso que coincida con el nombre dado: attr 'android: actionModeShareDrawable' appcompat-v7: 21.0.0 con compileSdkVersion 21
- ¿Cómo iniciar la transición de elementos compartidos usando Fragmentos?
- Implementación de Google play y mapas como la barra de búsqueda de Android
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 eliminar la sombra del botón (android)
- Implícito "Enviar" después de pulsar Hecho en el teclado en el último EditText