it-swarm.com.ru

Как анимировать элементы RecyclerView, когда они появляются

Как я могу анимировать элементы RecyclerView, когда они появляются?

Аниматор элемента по умолчанию анимируется только тогда, когда данные добавляются или удаляются после того, как были установлены данные переработчика. Я занимаюсь разработкой новых приложений и понятия не имею, с чего начать.

Есть идеи как этого добиться?

203
PaulNunezM

Правка :

Согласно документации ItemAnimator :

Этот класс определяет анимацию, которая происходит на элементах по мере внесения изменений в адаптер.

Поэтому, если вы не добавляете свои элементы один за другим в свою RecyclerView и не обновляете представление на каждой итерации, я не думаю, что ItemAnimator - это решение ваших потребностей.

Вот как вы можете анимировать элементы RecyclerView, когда они появляются с помощью CustomAdapter:

public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.ViewHolder>
{
    private Context context;

    // The items to display in your RecyclerView
    private ArrayList<String> items;
    // Allows to remember the last item shown on screen
    private int lastPosition = -1;

    public static class ViewHolder extends RecyclerView.ViewHolder
    {
        TextView text;
        // You need to retrieve the container (ie the root ViewGroup from your custom_item_layout)
        // It's the view that will be animated
        FrameLayout container;

        public ViewHolder(View itemView)
        {
            super(itemView);
            container = (FrameLayout) itemView.findViewById(R.id.item_layout_container);
            text = (TextView) itemView.findViewById(R.id.item_layout_text);
        }
    }

    public CustomAdapter(ArrayList<String> items, Context context)
    {
        this.items = items;
        this.context = context;
    }

    @Override
    public CustomAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
    {
        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.custom_item_layout, parent, false);
        return new ViewHolder(v);
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position)
    {
        holder.text.setText(items.get(position));

        // Here you apply the animation when the view is bound
        setAnimation(holder.itemView, position);
    }

    /**
     * Here is the key method to apply the animation
     */
    private void setAnimation(View viewToAnimate, int position)
    {
        // If the bound view wasn't previously displayed on screen, it's animated
        if (position > lastPosition)
        {
            Animation animation = AnimationUtils.loadAnimation(context, Android.R.anim.slide_in_left);
            viewToAnimate.startAnimation(animation);
            lastPosition = position;
        }
    }
}

И ваш custom_item_layout будет выглядеть так:

<FrameLayout
    Android:id="@+id/item_layout_container"
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content">

    <TextView
        Android:id="@+id/item_layout_text"
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        Android:textAppearance="?android:attr/textAppearanceListItemSmall"
        Android:gravity="center_vertical"
        Android:minHeight="?android:attr/listPreferredItemHeightSmall"/>

</FrameLayout>

Для получения дополнительной информации о CustomAdapters и RecyclerView, обратитесь к этому обучение в официальной документации .

Проблемы с быстрой прокруткой

Использование этого метода может вызвать проблемы с быстрой прокруткой. Представление может быть повторно использовано во время анимации. Во избежание этого рекомендуется очищать анимацию при отсоединении.

    @Override
    public void onViewDetachedFromWindow(final RecyclerView.ViewHolder holder)
    {
        ((CustomViewHolder)holder).clearAnimation();
    }

На CustomViewHolder:

    public void clearAnimation()
    {
        mRootLayout.clearAnimation();
    }

Старый ответ:

Посмотрите на репозиторий Габриэле Мариотти , я уверен, вы найдете то, что вам нужно. Он предоставляет простые ItemAnimators для RecyclerView, такие как SlideInItemAnimator или SlideScaleItemAnimator.

291
MathieuMaree

Я анимировал появление элементов Recyclerview, когда они впервые появляются, как показано в коде ниже. Возможно, это кому-нибудь пригодится.

private final static int FADE_DURATION = 1000; //FADE_DURATION in milliseconds

@Override
public void onBindViewHolder(ViewHolder holder, int position) {

    holder.getTextView().setText("some text");

    // Set the view to fade in
    setFadeAnimation(holder.itemView);            
}

private void setFadeAnimation(View view) {
    AlphaAnimation anim = new AlphaAnimation(0.0f, 1.0f);
    anim.setDuration(FADE_DURATION);
    view.startAnimation(anim);
}

Вы также можете заменить setFadeAnimation() на следующую setScaleAnimation(), чтобы оживить внешний вид элементов путем их масштабирования из точки:

private void setScaleAnimation(View view) {
    ScaleAnimation anim = new ScaleAnimation(0.0f, 1.0f, 0.0f, 1.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
    anim.setDuration(FADE_DURATION);
    view.startAnimation(anim);
}

Приведенный выше код имеет некоторые недостатки, поскольку при прокрутке элементы RecyclerView всегда исчезают или масштабируются. Если вы хотите, вы можете добавить код, чтобы позволить анимации происходить при первом создании фрагмента или действия, содержащего RecyclerView (например, получить системное время при создании и разрешить анимацию только в течение первых миллисекунд FADE_DURATION).

53
pbm

Я создал анимацию из ответа pbm с небольшим modification, чтобы анимация запускалась только один раз 

в другом слове Animation appear with you scroll down only 

private int lastPosition = -1;

private void setAnimation(View viewToAnimate, int position) {
    // If the bound view wasn't previously displayed on screen, it's animated
    if (position > lastPosition) {
        ScaleAnimation anim = new ScaleAnimation(0.0f, 1.0f, 0.0f, 1.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
        anim.setDuration(new Random().nextInt(501));//to make duration random number between [0,501)
        viewToAnimate.startAnimation(anim);
        lastPosition = position;
    }
}

и в onBindViewHolder вызвать функцию 

@Override
public void onBindViewHolder(ViewHolder holder, int position) {

holder.getTextView().setText("some text");

// call Animation function
setAnimation(holder.itemView, position);            
}
21
Basheer AL-MOMANI

Вы можете добавить атрибут Android: layoutAnimation = "@ anim/rv_item_animation" в RecyclerView следующим образом:

<Android.support.v7.widget.RecyclerView
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"                                        
    Android:layoutAnimation="@anim/layout_animation_fall_down"
    />

спасибо за отличную статью здесь: https://proandroiddev.com/enter-animation-using-recyclerview-and-layoutanimation-part-1-list-75a874a5d213

11
Pavel Biryukov

Хорошее место для начала это: https://github.com/wasabeef/recyclerview-animators/blob/master/animators/src/main/Java/jp/wasabeef/recyclerview/adapters/AnimationAdapter.Java

Вам даже не нужна полная библиотека, этого класса достаточно .. Тогда, если вы просто реализуете свой класс Adapter, предоставляя аниматор, подобный этому:

@Override
protected Animator[] getAnimators(View view) {
    return new Animator[]{
            ObjectAnimator.ofFloat(view, "translationY", view.getMeasuredHeight(), 0)
    };
}

@Override
public long getItemId(final int position) {
    return getWrappedAdapter().getItemId(position);
}

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

8
Alessandro Crugnola

Анимация элементов в представлении переработчика, когда они связаны в адаптере, может быть не самой лучшей идеей, так как это может привести к тому, что элементы в обзоре переработчика будут анимироваться на разных скоростях. В моем случае, предмет в конце окна рециркуляции оживляет свою позицию быстрее, чем те, что наверху, так как те, что наверху, должны перемещаться дальше, так что это выглядит неопрятно.

Оригинальный код, который я использовал для анимации каждого элемента в представлении реселлера, можно найти здесь:

http://frogermcs.github.io/Instagram-with-Material-Design-concept-is-getting-real/

Но я скопирую и вставлю код в случае разрыва ссылки.

STEP 1: Установите это внутри вашего метода onCreate, чтобы обеспечить запуск анимации только один раз:

if (savedInstanceState == null) {
    pendingIntroAnimation = true;
}

STEP 2: Вам нужно будет поместить этот код в метод, с которого вы хотите запустить анимацию:

if (pendingIntroAnimation) {
    pendingIntroAnimation = false;
    startIntroAnimation();
}

В ссылке писатель анимирует значки панели инструментов, поэтому он поместил его в этот метод:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.menu_main, menu);
    inboxMenuItem = menu.findItem(R.id.action_inbox);
    inboxMenuItem.setActionView(R.layout.menu_item_view);
    if (pendingIntroAnimation) {
        pendingIntroAnimation = false;
        startIntroAnimation();
    }
    return true;
}

ШАГ 3: Теперь напишите логику для startIntroAnimation ():

private static final int ANIM_DURATION_TOOLBAR = 300;

private void startIntroAnimation() {
    btnCreate.setTranslationY(2 * getResources().getDimensionPixelOffset(R.dimen.btn_fab_size));

    int actionbarSize = Utils.dpToPx(56);
    toolbar.setTranslationY(-actionbarSize);
    ivLogo.setTranslationY(-actionbarSize);
    inboxMenuItem.getActionView().setTranslationY(-actionbarSize);

    toolbar.animate()
            .translationY(0)
            .setDuration(ANIM_DURATION_TOOLBAR)
            .setStartDelay(300);
    ivLogo.animate()
            .translationY(0)
            .setDuration(ANIM_DURATION_TOOLBAR)
            .setStartDelay(400);
    inboxMenuItem.getActionView().animate()
            .translationY(0)
            .setDuration(ANIM_DURATION_TOOLBAR)
            .setStartDelay(500)
            .setListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    startContentAnimation();
                }
            })
            .start();
}

Моя предпочтительная альтернатива:

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

ШАГ 1 и 2 остаются прежними.

В ШАГЕ 3, как только ваш вызов API возвращается с вашими данными, я запускаю анимацию.

private void startIntroAnimation() {
    recyclerview.setTranslationY(latestPostRecyclerview.getHeight());
    recyclerview.setAlpha(0f);
    recyclerview.animate()
            .translationY(0)
            .setDuration(400)
            .alpha(1f)
            .setInterpolator(new AccelerateDecelerateInterpolator())
            .start();
}

Это оживило бы все ваше представление о переработчике так, чтобы оно отображалось в нижней части экрана.

3
Simon

Создайте этот метод в вашем recyclerview Adapter

private void setZoomInAnimation(View view) {
        Animation zoomIn = AnimationUtils.loadAnimation(context, R.anim.zoomin);// animation file 
        view.startAnimation(zoomIn);
    }

И, наконец, добавьте эту строку кода вonBindViewHolder

setZoomInAnimation(holder.itemView);

2
Md.Tarikul Islam

Добавьте эту строку в RecyclerView.xml

Android:animateLayoutChanges="true"
0
Avinash Verma

Просто расширяет ваш адаптер, как показано ниже 

public class RankingAdapter extends AnimatedRecyclerView<RankingAdapter.ViewHolder> 

И добавить супер метод к onBindViewHolder

@Override
    public void onBindViewHolder(ViewHolder holder, final int position) {
        super.onBindViewHolder(holder, position);

Это автоматизированный способ создания анимированного адаптера типа «Basheer AL-MOMANI».

import Android.support.v7.widget.RecyclerView;
import Android.view.View;
import Android.view.ViewGroup;
import Android.view.animation.Animation;
import Android.view.animation.ScaleAnimation;

import Java.util.Random;

/**
 * Created by eliaszkubala on 24.02.2017.
 */
public class AnimatedRecyclerView<T extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<T> {


    @Override
    public T onCreateViewHolder(ViewGroup parent, int viewType) {
        return null;
    }

    @Override
    public void onBindViewHolder(T holder, int position) {
        setAnimation(holder.itemView, position);
    }

    @Override
    public int getItemCount() {
        return 0;
    }

    protected int mLastPosition = -1;

    protected void setAnimation(View viewToAnimate, int position) {
        if (position > mLastPosition) {
            ScaleAnimation anim = new ScaleAnimation(0.0f, 1.0f, 0.0f, 1.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
            anim.setDuration(new Random().nextInt(501));//to make duration random number between [0,501)
            viewToAnimate.startAnimation(anim);
            mLastPosition = position;
        }
    }

}
0
EliaszKubala

Без кодирования.

Посетите Gist Link

  <?xml version="1.0" encoding="utf-8"?>
<layoutAnimation xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:animation="@anim/item_animation_fall_down"
    Android:animationOrder="normal"
    Android:delay="15%" />

<translate
    Android:fromYDelta="-20%"
    Android:toYDelta="0"
    Android:interpolator="@Android:anim/decelerate_interpolator"
    />

<alpha
    Android:fromAlpha="0"
    Android:toAlpha="1"
    Android:interpolator="@Android:anim/decelerate_interpolator"
    />

<scale
    Android:fromXScale="105%"
    Android:fromYScale="105%"
    Android:toXScale="100%"
    Android:toYScale="100%"
    Android:pivotX="50%"
    Android:pivotY="50%"
    Android:interpolator="@Android:anim/decelerate_interpolator"
    />

Используйте в макетах и ​​recylcerview, как:

<Android.support.v7.widget.RecyclerView
            Android:id="@+id/recycler_view"
            Android:layout_width="match_parent"
            Android:layout_height="wrap_content"
            Android:layoutAnimation="@anim/layout_animation"
            app:layout_behavior="@string/appbar_scrolling_view_behavior" />
0
Na Ran