Mostrar y ocultar una Vista con una animación de deslizamiento hacia arriba/abajo

Tengo un LinearLayout que quiero mostrar u ocultar con una Animación que empuja el layout hacia arriba o hacia abajo cada vez que cambio su visibilidad.

He visto algunos ejemplos por ahí pero ninguno se ajusta a mis necesidades.

He creado dos archivos xml para las animaciones pero no sé cómo iniciarlas cuando cambio la visibilidad de un LinearLayout.

Solución

Con la nueva API de animación que se introdujo en Android 3.0 (Honeycomb) es muy sencillo crear dichas animaciones.

Deslizar una Vista hacia abajo por una distancia:

view.animate().translationY(distance);

Más tarde puede deslizar la Vista de vuelta a su posición original así:

view.animate().translationY(0);

También puede combinar fácilmente varias animaciones. La siguiente animación deslizará una Vista hacia abajo por su altura y la desvanecerá al mismo tiempo:

// Prepare the View for the animation
view.setVisibility(View.VISIBLE);
view.setAlpha(0.0f);

// Start the animation
view.animate()
    .translationY(view.getHeight())
    .alpha(1.0f)
    .setListener(null);

A continuación, puede desvanecerse la "Vista" de nuevo y deslizarla de nuevo a su posición original. También establecemos un AnimatorListener para poder devolver la visibilidad de la Vista a GONE una vez que la animación haya terminado:

view.animate()
    .translationY(0)
    .alpha(0.0f)
    .setListener(new AnimatorListenerAdapter() {
        @Override
        public void onAnimationEnd(Animator animation) {
            super.onAnimationEnd(animation);
            view.setVisibility(View.GONE);
        }
    });
Comentarios (22)

Puedes iniciar la Animación correcta cuando la visibilidad del LinearLayout cambia creando una nueva subclase de LinearLayout y anulando setVisibility() para iniciar las Animaciones. Considera algo como esto:

public class SimpleViewAnimator extends LinearLayout
{
    private Animation inAnimation;
    private Animation outAnimation;

    public SimpleViewAnimator(Context context)
    {
        super(context);
    }

    public void setInAnimation(Animation inAnimation)
    {
        this.inAnimation = inAnimation;
    }

    public void setOutAnimation(Animation outAnimation)
    {
        this.outAnimation = outAnimation;
    }

    @Override
    public void setVisibility(int visibility)
    {
        if (getVisibility() != visibility)
        {
            if (visibility == VISIBLE)
            {
                if (inAnimation != null) startAnimation(inAnimation);
            }
            else if ((visibility == INVISIBLE) || (visibility == GONE))
            {
                if (outAnimation != null) startAnimation(outAnimation);
            }
        }

        super.setVisibility(visibility);
    }
}
Comentarios (7)
if (filter_section.getVisibility() == View.GONE) {
    filter_section.animate()
            .translationY(filter_section.getHeight()).alpha(1.0f)
            .setListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationStart(Animator animation) {
                    super.onAnimationStart(animation);
                    filter_section.setVisibility(View.VISIBLE);
                    filter_section.setAlpha(0.0f);
                }
            });
} else {
    filter_section.animate()
            .translationY(0).alpha(0.0f)
            .setListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    super.onAnimationEnd(animation);
                    filter_section.setVisibility(View.GONE);
                }
            });
}
Comentarios (5)