RecyclerViewアイテムが表示されたときにアニメーション化する方法


237

表示されているRecyclerViewアイテムをアニメーション化するにはどうすればよいですか?

デフォルトのアイテムアニメーターは、リサイクラーデータが設定された後にデータが追加または削除されたときにのみアニメーション化します。私は新しいアプリケーションを開発しているので、どこから始めればよいのかわかりません。

これを達成する方法はありますか?

回答:


42

XMLのみでシンプルに

Gist Linkにアクセス

res / anim / layout_animation.xml

<?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%" />

res / anim / item_animation_fall_down.xml

<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="500">

    <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"
        />

</set>

次のようなレイアウトと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" />

1
@ArnoldBrownアニメーションファイルを変更する。参照:stackoverflow.com/questions/5151591/…–
iamnaran

これは断然最も実用的な答えです。
Oliver Metz

リストが開かれるたびにこれを機能させる方法。これは初めて行うだけだからです。
Hiwa Jalal

7
recyclerView.scheduleLayoutAnimation()データセットが変更された後に呼び出す必要があります。変更しないと、アニメーションが機能しません。
zeleven

これは、アイテムがリサイクルされて再び表示されるときに機能しますか?私はこのソリューションを試してみましたが、最初のアニメーションがレイアウトを最初に表示したときにうまくいきます。スクロールした後、表示に戻ったときにアイテムにアニメーションが表示されません。
Jason p

315

編集:

ItemAnimatorのドキュメントによると

このクラスは、アダプターが変更されたときにアイテムで発生するアニメーションを定義します。

したがって、アイテムを1つずつ追加しない限り、 RecyclerView、各反復でビューを更新し、私は考えていませんItemAnimatorあなたのニーズに対する解決策でます。

RecyclerViewCustomAdapterを使用して表示されるときに、項目をアニメーション化する方法を次に示します。

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

古い答え:

で外観を与えるガブリエレMariottiのレポ、私はかなり確信して、あなたが必要なものを見つけることができますよ。彼は、SlideInItemAnimatorやSlideScaleItemAnimatorなどのRecyclerViewにシンプルなItemAnimatorsを提供しています。


1
私はそれを見ましたが、それはそれらが現れた後にアイテムを追加したり削除したりするためのものです。彼らが現れる前にアニメーションを開始する必要があります。とにかくマシューに感謝します。
PaulNunezM 2014年

1
私の知る限り、その場合はCustomAdapterを使用する必要があります。
MathieuMaree 2014年

20
RecyclerViewでこれらのアニメーションを使用して「スタック」エフェクトを経験し、解決した可能性があるかどうか疑問に思いましたか?ListViewに同様のコードを使用しましたが、スクロールした速度に関係なく問題なくアニメーション化されましたが、RecyclerViewを使用すると、高速でスクロールすると、一部のアイテムが他のアイテムの上にくっついて完全に非表示にならないことがあります。 -アニメーションが終了する前に停止したようです。実際にフィールドにデータを入力するコードの一部をコメントアウトしてみたので(onBindViewHolderメソッドの実行を高速化しようとしました)、animatのコードを残しました
Tomislav

4
@MathieuMareeこの驚くべきアニメーションをありがとうございます。遅いスクロールには適しているように見えますが、速いスクロールのrecyclerviewアイテムが重複しています。この問題を見つけましたか?この問題を克服するための提案がありますか?
Giru Bhai 2015

40
@GiruBhaiをオーバーライドonViewDetachedFromWindowclearAnimationて、ビューを呼び出します。問題は、RecyclerViewがビューを再利用しようとしているときに実行中のアニメーションがあることです。
Xample

62

のフェードインをアニメーション化しました 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ミリ秒の間のみアニメーションを許可します)。


1
スクロールダウンのみでアニメーションが機能するように、あなたの回答を少し修正しました。私の回答を
Basheer AL-MOMANI

1
これにより、上下に高速スクロールすると、レイアウト(上書きされたリストアイテム、一部のアイテムのテキストの色が間違っている)が
損なわ

これは、recyclerviewアイテムをアニメーション化する適切または推奨される方法ではありません。ItemAnimatorクラスを使用している必要があります
Eco4ndly '

25

私はからアニメーションを作成したPBMの答え少しでmodification一度だけaninmationランを作るために

つまり、 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);            
}

1
ここでlastPositionとは何ですか?それはarrayList.size()です-1
Sumit Shukla

1
lastPositionレンダリングされたビューの数を表すため、その値の始まりです-1。新しいビューがレンダリングされるたびに、アニメーションを開始して位置を増やします
Basheer AL-MOMANI

15

次のように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


これは、recyclerviewが最初に読み込まれたときに機能しましたが、新しいアイテムを追加したときには機能しませんでした。(私はそれがとても良い仕事だったと思いますが)
C. Skjerdal

8

開始するのに適した場所は次のとおりです。https//github.com/wasabeef/recyclerview-animators/blob/master/animators/src/main/java/jp/wasabeef/recyclerview/adapters/AnimationAdapter.java

完全なライブラリも必要ありません。そのクラスで十分です。次に、次のようなアニメーターを指定してアダプタークラスを実装する場合:

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

下にスクロールするとアイテムが表示され、高速スクロールの問題も回避されます。


3

アダプターにバインドされているときにrecyclerview内のアイテムをアニメーション化することは、recyclerview内のアイテムをさまざまな速度でアニメーション化する可能性があるため、最善の方法とは言えません。私の場合、recyclerviewの最後にあるアイテムは、一番上にあるアイテムがさらに移動する必要があるため、一番上にあるアイテムよりも速くアニメーション化され、見た目がすっきりします。

各アイテムをrecyclerviewにアニメーション化するために使用した元のコードは、次の場所にあります。

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

ただし、リンクが切れた場合に備えて、コードをコピーして貼り付けます。

ステップ1:これをonCreateメソッド内に設定して、アニメーションが1回だけ実行されるようにします。

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

ステップ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();
}

私が好む代替案:

私はむしろ、recyclerview内のアイテムではなく、recyclerview全体をアニメーション化したいと思います。

ステップ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();
}

これにより、recyclerview全体がアニメーション化され、画面の下部から飛ぶようになります。


あなたは
recyclerview

はい、そうです。リサイクラービュー全体をアニメーション化する方が各項目よりも優れていると思う理由の最初の段落を読む必要があります。各アイテムをアニメーション化してみることができますが、見栄えがよくありません。
Simon

なにlatestPostRecyclerview
アントニオ

1
回答の最初の段落を読みましたか。アイテムビューのアニメーション化がそれほど優れていない理由を述べましたか。また、私は受け入れられた解決策を試してみることをお勧めします、そしてあなたは問題に気づき、戻ってこの解決策を試してください。
Simon

3

このメソッドをrecyclerviewアダプターに作成します

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

そして最後に、このコード行をonBindViewHolderに追加します

setZoomInAnimation(holder.itemView);


2

2019年には、すべてのアイテムアニメーションをItemAnimatorに入れることをお勧めします。

まず、recycler-viewでアニメーターを宣言します。

with(view.recycler_view) {
adapter = Adapter()
itemAnimator = CustomAnimator()
}

次に、カスタムアニメーターを宣言します。

class CustomAnimator() : DefaultItemAnimator() {

     override fun animateAppearance(
       holder: RecyclerView.ViewHolder,
       preInfo: ItemHolderInfo?,
       postInfo: ItemHolderInfo): Boolean{} // declare  what happens when a item appears on the recycler view

     override fun animatePersistence(
       holder: RecyclerView.ViewHolder,
       preInfo: ItemHolderInfo,
       postInfo: ItemHolderInfo): Boolean {} // declare animation for items that persist in a recycler view even when the items change

}

上記のものと同様に、消滅animateDisappearance用、追加animateAdd用、変更用animateChange、移動用があります。animateMoveます。

重要なポイントの1つは、内部の正しいアニメーションディスパッチャを呼び出すことです。


このオーバーライド機能を使用したカスタムの外観アニメーションの例を教えていただけませんか?例を見つけることができず、関数でアニメーションを指定する必要があるかどうかわかりません。
ミナー

1
gist.github.com/tadfisher/120d03f8380bfa8a16bfクイック検索でオンラインで見つけたので、過負荷がどのように機能するかがわかります
Dinesh

0

以下のようにアダプタを拡張するだけです

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

私は、次のように使用する方が良いと思います:(RecyclerView アダプターでは、1つのメソッドのみをオーバーライドします)

override fun onViewAttachedToWindow(holder: ViewHolder) {
    super.onViewAttachedToWindow(holder)

    setBindAnimation(holder)
}

RVのすべてのアタッチアニメーションが必要な場合。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.