web-dev-qa-db-ja.com

notifyItemChangedのアニメーションを無効にするためにRecyclerViewのItemAnimatorを実装する方法

私のプロジェクトでは、RecyclerViewnotifyItemChangedの「変更」アニメーションを無効にする必要があります。

私はRecyclerViewのソースを調査し、以下のようにAndroid.support.v7.widget.DefaultItemAnimatorをオーバーライドしました。

private static  class ItemAnimator extends DefaultItemAnimator
{
    @Override
    public boolean animateChange(RecyclerView.ViewHolder oldHolder, RecyclerView.ViewHolder newHolder, int fromX, int fromY, int toX, int toY) {
        if(oldHolder != null)
        {
            oldHolder.itemView.setVisibility(View.INVISIBLE);
            dispatchChangeFinished(oldHolder, true);
        }

        if(newHolder != null)
        {
            dispatchChangeFinished(newHolder, false);
        }

        return false;
    }
}

しかし、Googleドキュメントの仕様と一致するかどうかはわかりません: RecyclerView.ItemAnimator.animateChange

私の理解したソースコードによると、メソッドを適切にオーバーライドしないと、oldHolderはリサイクルされません

animateChangeを正しい方法でオーバーライドする方法を見つけてください。

57
Kenny

私はちょうどanimateChangeを削除する正しいソリューションを見つけました。

とても簡単です。 Googleは機能を実装しました。

((SimpleItemAnimator) RecyclerView.getItemAnimator()).setSupportsChangeAnimations(false);

ドキュメント: setSupportsChangeAnimations

109
Kenny

同じ問題がありました。 notifyItemChangedを呼び出すと、赤いオーバーレイが点滅していました。あなたのコードを試した後、私は単に呼び出してデフォルトのAnimatorを最終的に削除しました

recyclerView.setItemAnimator(null);

recyclerViewで。

49
Saenic

Googleがサポートライブラリ23.1.0のメソッドsetSupportsChangeAnimations()(しかし、なぜ?)を削除するため、@ Kennyの回答はもう機能しませんでした。

場合によっては、setChangeDuration(0)が回避策として機能します。

@editそのようなものを使用することをお勧めします:

  RecyclerView.ItemAnimator animator = recyclerView.getItemAnimator();
        if (animator instanceof SimpleItemAnimator) {
            ((SimpleItemAnimator) animator).setSupportsChangeAnimations(false);
        }
8
Shu

誰かが私のようにつまずいたとしても:
どういうわけかsetSupportsChangeAnimations(false)は機能しませんでしたが、recyclerView.getItemAnimator().setChangeDuration(0)はアニメーションをうまく削除しました。

4
Touhid

DefaultItemAnimatorによって指定されたすべてのアニメーションを保持したいが、ビューが更新されるたびに発生する「点滅」アニメーションを削除したいすべての人のためのソリューションが見つかった場合。

最初に、DefaultItemAnimatorのソースコードを取得します。プロジェクトに同じ名前のクラスを作成します。

次に、次のように、ItemAnimatorを変更したDefaultItemAnimatorの新しいインスタンスに設定します。

recyclerView.setItemAnimator(new MyItemAnimator());

次に、新しいクラスのソースコードに移動し、メソッドを見つけます

animateChangeImpl(final ChangeInfo changeInfo) { ... }

ここで、アルファ値を変更するメソッド呼び出しを見つける必要があります。次の2行を見つけて、.alpha(0)と.alpha(1)を削除します

oldViewAnim.alpha(0).setListener(new VpaListenerAdapter() { ... }
newViewAnimation.translationX(0).translationY(0).setDuration(getChangeDuration()).alpha(1).setListener(new VpaListenerAdapter() { ... }

そのようです

oldViewAnim.setListener(new VpaListenerAdapter() { ... }
newViewAnimation.translationX(0).translationY(0).setDuration(getChangeDuration()).setListener(new VpaListenerAdapter() { ... }
4
Alex

最も簡単な解決策は、コンストラクターでDefaultItemAnimatorを拡張し、setSupportsChangeAnimationsfalseに設定することです。

public class DefaultItemAnimatorNoChange extends DefaultItemAnimator {
    public DefaultItemAnimatorNoChange() {
        setSupportsChangeAnimations(false);
    }
}
2
rafakob