Android: показать / скрыть представление с помощью анимации

81

Я просматривал много результатов / вопросов Google здесь, чтобы определить, как показать / скрыть представление с помощью вертикальной анимации, но я не могу найти тот, который точно или не слишком расплывчатый.

У меня есть макет (панель отмены), который находится под другим макетом и над несколькими другими виджетами; эта полоса отмены должна открываться и закрываться вертикально в зависимости от обстоятельств.

В настоящее время все, что я делаю прямо сейчас, - это отображение или исчезновение представления.

Бласкович
источник

Ответы:

64

Установите атрибут android:animateLayoutChanges="true" внутри родительского макета.

Поместите вид в макет, если его нет, и установите android:animateLayoutChanges="true"для этого макета.

ПРИМЕЧАНИЕ. Это работает только с API уровня 11+ (Android 3.0).

Pozuelog
источник
19

Я создал расширение для RelativeLayoutотображения / скрытия макетов с анимацией. ViewЧтобы получить эти функции, он может расширять любой вид .

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

Вы можете переопределить исходный Animations, используя overrideDefaultInAnimationиoverrideDefaultOutAnimation

Мои оригинальные анимации были fadeIn / Out, я добавляю файлы анимации XML для перевода в / из экрана (перевод вверх и сверху)

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" />
Ротеммиз
источник
15

Это может быть достигнуто с помощью однострочного оператора в API 12 и выше. Ниже приведен пример vпредставления, которое вы хотите оживить;

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

Это Viewсдвинет рассматриваемый вопрос влево на 1000 пикселей. Чтобы вернуть представление обратно в пользовательский интерфейс, мы можем просто сделать следующее.

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

Надеюсь, кому-то это пригодится.

Руди Кершоу
источник
11

Если вы хотите анимировать только высоту представления (скажем, от 0 до определенного числа), вы можете реализовать свою собственную анимацию:

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);
Андреас Берхайм Бруден
источник
7

Я использовал эти две функции, чтобы плавно скрыть и показать вид с анимацией перехода.

@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();

            }
        });
    }
Джитендра рамолия
источник
4

Попробуйте использовать класс TranslateAnimation , который создает анимацию для изменения положения. Попробуйте прочитать это, чтобы получить помощь - http://developer.android.com/reference/android/view/animation/TranslateAnimation.html

Обновление: вот пример этого. Если у вас высота обзора 50, а в режиме скрытия вы хотите отображать только 10 пикселей. Пример кода будет -

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

PS: Есть много или других методов, которые помогут вам использовать анимацию в соответствии с вашими потребностями. Также обратите внимание на RelativeLayout.LayoutParams, если вы хотите полностью настроить код, однако с помощью TranslateAnimation проще использовать.

РЕДАКТИРОВАТЬ: -Сложная версия с использованием 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);

В этом примере кода предполагается, что вы помещаете свое представление в RelativeLayout, если не измените имя макета, однако другой макет может не работать. Если вы хотите создать для них эффект анимации, медленно уменьшайте или увеличивайте значение topMargin. Вы также можете рассмотреть возможность использования Thread.sleep ().

нуб
источник
1
ScaleAnimation не меняет положение, а масштабирует вид ... Вы путаете TranslateAnimation.
Rotemmiz
Думаю, вы получили то, что вам нужно, а если нет, то вот пример кода - TranslateAnimation anim = new TranslateAnimation (fromX, toX, fromY, toY); view.setAnimation (аним);
noob
3

Попробуй это.

view.animate()
    .translationY(0)
    .alpha(0.0f)
    .setListener(new AnimatorListenerAdapter() {
        @Override
        public void onAnimationEnd(Animator animation) {
            super.onAnimationEnd(animation);
            view.setVisibility(View.GONE);
        }
    });
SaurabhG
источник
1

Прежде всего, получите высоту представления, которое хотите увидеть, и сделайте логическое значение для сохранения, если представление отображается:

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

Затем вызовите метод для отображения скрытия представления и измените значение логического значения:

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

Метод:

/**
     * 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
источник
1

ViewAnimator:

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

Функции:

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);
}
Анкуш Шривастава
источник