Android: показати / приховати вигляд за допомогою анімації


81

Тут я переглядав багато результатів / запитань Google, щоб визначити, як показати / приховати вигляд за допомогою вертикальної анімації, але, здається, я не можу знайти той, який є абсолютно правильним або не надто розмитим.

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

В даний час все, що я роблю зараз, - це налаштування подання на видимість або зникнення.

Відповіді:


64

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

Помістіть вигляд у макет, якщо його немає, і встановіть android:animateLayoutChanges="true"для цього макета.

ПРИМІТКА: Це працює лише з API рівня 11+ (Android 3.0)


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

Мої оригінальні анімації зникали / виходили, я додаю файли анімації 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 пікселів. Щоб повернути подання назад на UI, ми можемо просто зробити наступне.

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, якщо не змінюєте назву Layout, однак інший макет може не працювати. Якщо ви хочете надати на них ефект анімації, повільно зменшуйте або збільшуйте верхнє поле. Ви також можете розглянути можливість використання Thread.sleep ().


1
ScaleAnimation не змінює положення, він масштабує вигляд ... Ви плутаєте з TranslateAnimation.
Ротемміз

Я думаю, ви отримали те, що вам потрібно, і якщо ні, то ось зразок коду - TranslateAnimation anim = new TranslateAnimation (fromX, toX, fromY, toY); view.setAnimation (anim);
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);
        }
    });

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


        }

    }

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);
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.