Android: mostrar / ocultar una vista usando una animación

81

He estado revisando muchos resultados / preguntas de Google aquí para determinar cómo mostrar / ocultar una vista a través de una animación vertical, pero parece que no puedo encontrar uno que sea exactamente correcto o no demasiado vago.

Tengo un diseño (barra de deshacer) que está debajo de otro diseño y por encima de varios otros widgets; esta barra de deshacer debe abrirse y cerrarse verticalmente, según las circunstancias.

Actualmente, todo lo que hago ahora es configurar la vista para que sea visible o desaparezca.

Blaskovicz
fuente

Respuestas:

64

Establezca el atributo android:animateLayoutChanges="true" dentro del diseño principal.

Coloque la vista en un diseño si no es así y configúrelo android:animateLayoutChanges="true"para ese diseño.

NOTA: Esto solo funciona desde el nivel de API 11+ (Android 3.0)

pozuelog
fuente
19

Creé una extensión para RelativeLayoutmostrar / ocultar diseños con animaciones. Puede extender cualquier tipo de Viewpara obtener estas características.

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationSet;
import android.view.animation.AnimationUtils;
import android.widget.RelativeLayout;

public class AnimatingRelativeLayout extends RelativeLayout
{
    Context context;
    Animation inAnimation;
    Animation outAnimation;

    public AnimatingRelativeLayout(Context context)
    {
        super(context);
        this.context = context;
        initAnimations();

    }

    public AnimatingRelativeLayout(Context context, AttributeSet attrs)
    {
        super(context, attrs);
        this.context = context;
        initAnimations();
    }

    public AnimatingRelativeLayout(Context context, AttributeSet attrs, int defStyle)
    {
        super(context, attrs, defStyle);
        this.context = context;
        initAnimations();
    }

    private void initAnimations()
    {
        inAnimation = (AnimationSet) AnimationUtils.loadAnimation(context, R.anim.in_animation);
        outAnimation = (Animation) AnimationUtils.loadAnimation(context, R.anim.out_animation);
    }

    public void show()
    {
        if (isVisible()) return;
        show(true);
    }

    public void show(boolean withAnimation)
    {
        if (withAnimation) this.startAnimation(inAnimation);
        this.setVisibility(View.VISIBLE);
    }

    public void hide()
    {
        if (!isVisible()) return;
        hide(true);
    }

    public void hide(boolean withAnimation)
    {
        if (withAnimation) this.startAnimation(outAnimation);
        this.setVisibility(View.GONE);
    }

    public boolean isVisible()
    {
        return (this.getVisibility() == View.VISIBLE);
    }

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

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

Puede anular los originales Animationutilizando overrideDefaultInAnimationyoverrideDefaultOutAnimation

Mis animaciones originales fueron fadeIn / Out, estoy agregando archivos de animación XML para traducir dentro / fuera de la pantalla (Traducir hacia arriba y desde arriba)

in_animation.xml:

    <?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="600"
    android:fillAfter="false"
    android:fromXDelta="0"
    android:fromYDelta="-100%p"
    android:toXDelta="0"
    android:toYDelta="0" />

out_animation.xml:

  <?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="600"
    android:fillAfter="false"
    android:fromXDelta="0"
    android:fromYDelta="0"
    android:toXDelta="0"
    android:toYDelta="-100%p" />
Rotemmiz
fuente
15

Esto se puede lograr razonablemente en una declaración de una sola línea en API 12 y superior. A continuación se muestra un ejemplo de vla vista que desea animar;

v.animate().translationXBy(-1000).start();

Esto deslizará el Viewen cuestión hacia la izquierda 1000px. Para deslizar la vista de nuevo a la interfaz de usuario, simplemente podemos hacer lo siguiente.

v.animate().translationXBy(1000).start();

Espero que alguien lo encuentre útil.

Rudi Kershaw
fuente
11

Si solo desea animar la altura de una vista (de digamos 0 a un cierto número), puede implementar su propia animación:

final View v = getTheViewToAnimateHere();
Animation anim=new Animation(){
    protected void applyTransformation(float interpolatedTime, Transformation t) {
        super.applyTransformation(interpolatedTime, t);
        // Do relevant calculations here using the interpolatedTime that runs from 0 to 1
        v.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, (int)(30*interpolatedTime)));
    }};
anim.setDuration(500);
v.startAnimation(anim);
Andreas Berheim Brudin
fuente
7

He usado estas dos funciones para ocultar y mostrar la vista con animación de transición sin problemas.

@TargetApi(Build.VERSION_CODES.HONEYCOMB)
    public void expand(final View v, int duration, int targetHeight, final int position) {

        int prevHeight = v.getHeight();

        v.setVisibility(View.VISIBLE);
        ValueAnimator valueAnimator = ValueAnimator.ofInt(0, targetHeight);
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                v.getLayoutParams().height = (int) animation.getAnimatedValue();
                v.requestLayout();
            }
        });
        valueAnimator.setInterpolator(new DecelerateInterpolator());
        valueAnimator.setDuration(duration);
        valueAnimator.start();
        valueAnimator.addListener(new AnimatorListenerAdapter() {

            @Override
            public void onAnimationEnd(Animator animation) {
                v.clearAnimation();
            }
        });

    }

    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    public void collapse(final View v, int duration, int targetHeight, final int position) {
        if (position == (data.size() - 1)) {
            return;
        }
        int prevHeight = v.getHeight();
        ValueAnimator valueAnimator = ValueAnimator.ofInt(prevHeight, targetHeight);
        valueAnimator.setInterpolator(new DecelerateInterpolator());
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                v.getLayoutParams().height = (int) animation.getAnimatedValue();
                v.requestLayout();
            }
        });
        valueAnimator.setInterpolator(new DecelerateInterpolator());
        valueAnimator.setDuration(duration);
        valueAnimator.start();
        valueAnimator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                animBoolArray.put(position, false);
                v.clearAnimation();

            }
        });
    }
Jitendra ramoliya
fuente
4

Intente usar la clase TranslateAnimation , que crea la animación para los cambios de posición. Intente leer esto para obtener ayuda: http://developer.android.com/reference/android/view/animation/TranslateAnimation.html

Actualización: aquí está el ejemplo para esto. Si tiene la altura de su vista como 50 y en el modo de ocultar desea mostrar solo 10 px. El código de muestra sería:

TranslateAnimation anim=new TranslateAnimation(0,0,-40,0);
anim.setFillAfter(true);
view.setAnimation(anim);

PD: Hay muchos métodos u otros que le ayudarán a utilizar la animación de acuerdo con sus necesidades. También eche un vistazo a RelativeLayout.LayoutParams si desea personalizar completamente el código, sin embargo, usar TranslateAnimation es más fácil de usar.

EDITAR: -Versión compleja usando LayoutParams

RelativeLayout relParam=new RelativeLayout.LayoutParam(RelativeLayout.LayoutParam.FILL_PARENT,RelativeLayout.LayoutParam.WRAP_CONTENT); //you can give hard coded width and height here in (width,height) format.
relParam.topMargin=-50; //any number that work.Set it to 0, when you want to show it.
view.setLayoutParams(relparam);

Este código de ejemplo asume que está poniendo su vista en RelativeLayout, si no cambia el nombre de Layout, sin embargo, es posible que otro diseño no funcione. Si desea darles un efecto de animación, reduzca o aumente el topMargin lentamente. También puede considerar usar Thread.sleep () allí.

novato
fuente
1
ScaleAnimation no cambia de posición, escala la vista ... Estás confundiendo con TranslateAnimation.
Rotemmiz
Supongo que tienes lo que necesitas, y si no aquí hay un código de muestra - TranslateAnimation anim = new TranslateAnimation (fromX, toX, fromY, toY); view.setAnimation (anim);
novato
3

Prueba esto.

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

En primer lugar, obtenga la altura de la vista que desea ver y cree un valor booleano para guardar si la vista se muestra:

int heigth=0;
boolean showing=false;
LinearLayout layout = (LinearLayout) view.findViewById(R.id.layout);

        proDetailsLL.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {

            @Override
            public void onGlobalLayout() {
                // gets called after layout has been done but before display
                // so we can get the height then hide the view

                proHeight = proDetailsLL.getHeight(); // Ahaha!  Gotcha

                proDetailsLL.getViewTreeObserver().removeGlobalOnLayoutListener(this);
                proDetailsLL.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, 0));
            }
        });

Luego llame al método para mostrar ocultar la vista y cambie el valor del booleano:

slideInOutAnimation(showing, heigth, layout);
proShowing = !proShowing;

El método:

/**
     * Method to slide in out the layout
     * 
     * @param isShowing
     *            if the layout is showing
     * @param height
     *            the height to slide
     * @param slideLL
     *            the container to show
     */
private void slideInOutAnimation(boolean isShowing, int height, final LinearLayout slideLL, final ImageView arroIV) {

        if (!isShowing) {
        Animation animIn = new Animation() {
        protected void applyTransformation(float interpolatedTime, Transformation t) {
                    super.applyTransformation(interpolatedTime, t);
        // Do relevant calculations here using the interpolatedTime that runs from 0 to 1
        slideLL.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, (int) (heigth * interpolatedTime)));

                }
            };
            animIn.setDuration(500);
            slideLL.startAnimation(animIn);
        } else {

            Animation animOut = new Animation() {
                protected void applyTransformation(float interpolatedTime, Transformation t) {
                    super.applyTransformation(interpolatedTime, t);
                    // Do relevant calculations here using the interpolatedTime that runs from 0 to 1


                        slideLL.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT,
                                (int) (heigth * (1 - interpolatedTime))));

                }
            };
            animOut.setDuration(500);
            slideLL.startAnimation(animOut);


        }

    }
Jachumbelechao a Mantekilla
fuente
1

ViewAnimator:

En XML:

  <ViewAnimator
    android:id="@+id/animator_message"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:inAnimation="@anim/slide_down_text"
    android:outAnimation="@anim/slide_up_text">

    <TextView
        android:id="@+id/text_message_authentication"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center_horizontal"
        android:text="message_error_authentication" />

    <TextView
        android:id="@+id/text_message_authentication_connection"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center_horizontal"
        android:text="message_error_authentication_connection" />

    <TextView
        android:id="@+id/text_message_authentication_empty"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center_horizontal"
        android:text="message_error_authentication_field_empty" />

</ViewAnimator>

Funciones:

public void show(int viewId) {
    ViewAnimator animator = (ViewAnimator) findView(animatorId);
    View view = findViewById(viewId);

    if (animator.getDisplayedChild() != animator.indexOfChild(view)) {
        animator.setDisplayedChild(animator.indexOfChild(view));
     }
 }


 private void showAuthenticationConnectionFailureMessage() {
    show(R.id.text_message_authentication_connection);
}
Ankush Shrivastava
fuente