Как реализовать ItemAnimator RecyclerView, чтобы отключить анимацию notifyItemChanged

В моем проекте мне нужно отключить анимацию "change" RecyclerView, а notifyItemChanged.

Я исследовал в источнике 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.

Ответ 1

Я нашел правильное решение, чтобы просто удалить animateChange.

Это очень просто. Google реализовала функциональность.

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

Документация: setSupportsChangeAnimations

Ответ 2

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

recyclerView.setItemAnimator(null);

в RecyclerView.

Ответ 3

Ответ @Kenny больше не работает, потому что google remove method setSupportsChangeAnimations() (но почему?) в библиотеке поддержки 23.1.0.

В некотором случае setChangeDuration(0) может работать как обходной путь.

@edit Я предлагаю использовать что-то вроде этого:

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

Ответ 4

Если найдено решение, для всех, кто хочет сохранить все анимации, заданные DefaultItemAnimator, но избавиться от анимации "мигания", которая возникает каждый раз при обновлении представления.

Сначала получите исходный код DefaultItemAnimator. Создайте класс с таким же именем в вашем проекте.

Во-вторых, установите ItemAnimator в новый экземпляр модифицированного DefaultItemAnimator, например:

recyclerView.setItemAnimator(new MyItemAnimator());

Затем перейдите в исходный код новых классов и найдите метод

animateChangeImpl(final ChangeInfo changeInfo) { ... }

Теперь нам просто нужно найти вызов метода, изменяющий альфа-значения. Найдите следующие две строки и удалите .alpha(0) и α (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() { ... }

Ответ 5

Просто, если кто-то споткнется, как я:
 Каким-то образом setSupportsChangeAnimations(false) не работал у меня, но recyclerView.getItemAnimator().setChangeDuration(0) просто удалил анимацию.

Ответ 6

Самое простое решение - расширить DefaultItemAnimator и установить setSupportsChangeAnimations в false прямо в конструкторе:

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

Ответ 7

Ничто из перечисленного не помогло мне. Работало использование TransitionManager и установка перехода сцены в ноль.

TransitionManager.go(new Scene(recyclerView), null);

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

AutoTransition autoTransition = new AutoTransition();
TransitionManager.go(new Scene(recyclerView), autoTransition);