Android: pokaż / ukryj widok za pomocą animacji

81

Przeglądałem tutaj wiele wyników / pytań Google, aby określić, jak pokazać / ukryć widok za pomocą pionowej animacji, ale nie mogę znaleźć takiego, który byłby dokładnie poprawny lub niezbyt niejasny.

Mam układ (pasek cofania), który znajduje się poniżej innego układu i nad wieloma innymi widżetami; ten pasek cofania powinien otwierać się i zamykać w pionie, w zależności od okoliczności.

Obecnie wszystko, co teraz robię, to ustawianie widoku, aby był widoczny lub zniknął.

Blaskovicz
źródło

Odpowiedzi:

64

Ustaw atrybut android:animateLayoutChanges="true" wewnątrz układu nadrzędnego.

Umieść widok w układzie, jeśli nie jest, i ustaw android:animateLayoutChanges="true"dla tego układu.

UWAGA: Działa to tylko od poziomu API 11+ (Android 3.0)

pozuelog
źródło
19

Stworzyłem rozszerzenie, RelativeLayoutktóre pokazuje / ukrywa układy z animacjami. Może rozszerzyć dowolny rodzaj, Viewaby uzyskać te funkcje.

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;
    }
}

Możesz zastąpić oryginalne Animationpliki za pomocąoverrideDefaultInAnimation ioverrideDefaultOutAnimation

Moje oryginalne animacje znikały / znikały, dodaję pliki animacji XML do tłumaczenia w / z ekranu (Przetłumacz na górę i od góry)

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
źródło
15

Można to rozsądnie osiągnąć za pomocą pojedynczego wiersza instrukcji w API 12 i nowszych. Poniżej znajduje się przykład, w którym vjest widok, który chcesz animować;

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

Spowoduje to przesunięcie Viewpytania w lewo o 1000 pikseli. Aby przesunąć widok z powrotem do interfejsu użytkownika, możemy po prostu wykonać następujące czynności.

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

Mam nadzieję, że ktoś uzna to za przydatne.

Rudi Kershaw
źródło
11

Jeśli chcesz animować tylko wysokość widoku (od powiedzmy 0 do określonej liczby), możesz zaimplementować własną animację:

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
źródło
7

Użyłem tych dwóch funkcji do płynnego ukrywania i wyświetlania widoku z animacją przejścia.

@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
źródło
4

Spróbuj użyć klasy TranslateAnimation , która tworzy animację dla zmian pozycji. Spróbuj przeczytać to, aby uzyskać pomoc - http://developer.android.com/reference/android/view/animation/TranslateAnimation.html

Aktualizacja: Oto przykład. Jeśli masz wysokość swojego widoku na 50 iw trybie ukrywania chcesz pokazać tylko 10 pikseli. Przykładowy kod to -

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

PS: Istnieje wiele lub innych metod, które pomogą Ci użyć animacji zgodnie z Twoimi potrzebami. Przyjrzyj się również RelativeLayout.LayoutParams, jeśli chcesz całkowicie dostosować kod, jednak użycie TranslateAnimation jest łatwiejsze w użyciu.

EDYCJA: -Komplikowana wersja przy użyciu 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);

Ten przykładowy kod zakłada, że ​​umieszczasz swój widok w RelativeLayout, jeśli nie zmieniasz nazwy Layout, jednak inny układ może nie działać. Jeśli chcesz nadać im efekt animacji, powoli zmniejszaj lub zwiększaj górną margines. Możesz tam również rozważyć użycie Thread.sleep ().

Nowicjusz
źródło
1
ScaleAnimation nie zmienia pozycji, skaluje widok ... Mylisz się z TranslateAnimation.
Rotemmiz
Wydaje mi się, że masz to, czego potrzebujesz, a jeśli nie, to przykładowy kod - TranslateAnimation anim = new TranslateAnimation (fromX, toX, fromY, toY); view.setAnimation (anim);
noob
3

Spróbuj tego.

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

Przede wszystkim uzyskaj wysokość widoku, który chcesz zobaczyć i utwórz wartość logiczną do zapisania, jeśli widok jest wyświetlany:

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));
            }
        });

Następnie wywołaj metodę pokazującą ukryj widok i zmień wartość logiczną:

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

Metoda:

/**
     * 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 Unto Mantekilla
źródło
1

ViewAnimator:

W 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>

Funkcje:

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
źródło