public abstract class

SimpleItemAnimator

extends RecyclerView.ItemAnimator

 java.lang.Object

androidx.recyclerview.widget.RecyclerView.ItemAnimator

↳androidx.recyclerview.widget.SimpleItemAnimator

Subclasses:

DefaultItemAnimator

Gradle dependencies

compile group: 'androidx.recyclerview', name: 'recyclerview', version: '1.4.0-beta01'

  • groupId: androidx.recyclerview
  • artifactId: recyclerview
  • version: 1.4.0-beta01

Artifact androidx.recyclerview:recyclerview:1.4.0-beta01 it located at Google repository (https://maven.google.com/)

Androidx artifact mapping:

androidx.recyclerview:recyclerview com.android.support:recyclerview-v7

Androidx class mapping:

androidx.recyclerview.widget.SimpleItemAnimator android.support.v7.widget.SimpleItemAnimator

Overview

A wrapper class for ItemAnimator that records View bounds and decides whether it should run move, change, add or remove animations. This class also replicates the original ItemAnimator API.

It uses RecyclerView.ItemAnimator.ItemHolderInfo to track the bounds information of the Views. If you would like to extend this class, you can override RecyclerView.ItemAnimator.obtainHolderInfo() method to provide your own info class that extends RecyclerView.ItemAnimator.ItemHolderInfo.

Summary

Fields
from RecyclerView.ItemAnimatorFLAG_APPEARED_IN_PRE_LAYOUT, FLAG_CHANGED, FLAG_INVALIDATED, FLAG_MOVED, FLAG_REMOVED
Constructors
publicSimpleItemAnimator()

Methods
public abstract booleananimateAdd(RecyclerView.ViewHolder holder)

Called when an item is added to the RecyclerView.

public abstract booleananimateAppearance(RecyclerView.ViewHolder viewHolder, RecyclerView.ItemAnimator.ItemHolderInfo preLayoutInfo, RecyclerView.ItemAnimator.ItemHolderInfo postLayoutInfo)

Called by the RecyclerView when a ViewHolder is added to the layout.

public abstract booleananimateChange(RecyclerView.ViewHolder oldHolder, RecyclerView.ViewHolder newHolder, int fromLeft, int fromTop, int toLeft, int toTop)

Called when an item is changed in the RecyclerView, as indicated by a call to RecyclerView.Adapter.notifyItemChanged(int) or RecyclerView.Adapter.notifyItemRangeChanged(int, int).

public abstract booleananimateChange(RecyclerView.ViewHolder oldHolder, RecyclerView.ViewHolder newHolder, RecyclerView.ItemAnimator.ItemHolderInfo preLayoutInfo, RecyclerView.ItemAnimator.ItemHolderInfo postLayoutInfo)

Called by the RecyclerView when an adapter item is present both before and after the layout and RecyclerView has received a RecyclerView.Adapter.notifyItemChanged(int) call for it.

public abstract booleananimateDisappearance(RecyclerView.ViewHolder viewHolder, RecyclerView.ItemAnimator.ItemHolderInfo preLayoutInfo, RecyclerView.ItemAnimator.ItemHolderInfo postLayoutInfo)

Called by the RecyclerView when a ViewHolder has disappeared from the layout.

public abstract booleananimateMove(RecyclerView.ViewHolder holder, int fromX, int fromY, int toX, int toY)

Called when an item is moved in the RecyclerView.

public abstract booleananimatePersistence(RecyclerView.ViewHolder viewHolder, RecyclerView.ItemAnimator.ItemHolderInfo preLayoutInfo, RecyclerView.ItemAnimator.ItemHolderInfo postLayoutInfo)

Called by the RecyclerView when a ViewHolder is present in both before and after the layout and RecyclerView has not received a RecyclerView.Adapter.notifyItemChanged(int) call for it or a RecyclerView.Adapter.notifyDataSetChanged() call.

public abstract booleananimateRemove(RecyclerView.ViewHolder holder)

Called when an item is removed from the RecyclerView.

public booleancanReuseUpdatedViewHolder(RecyclerView.ViewHolder viewHolder)

public final voiddispatchAddFinished(RecyclerView.ViewHolder item)

Method to be called by subclasses when an add animation is done.

public final voiddispatchAddStarting(RecyclerView.ViewHolder item)

Method to be called by subclasses when an add animation is being started.

public final voiddispatchChangeFinished(RecyclerView.ViewHolder item, boolean oldItem)

Method to be called by subclasses when a change animation is done.

public final voiddispatchChangeStarting(RecyclerView.ViewHolder item, boolean oldItem)

Method to be called by subclasses when a change animation is being started.

public final voiddispatchMoveFinished(RecyclerView.ViewHolder item)

Method to be called by subclasses when a move animation is done.

public final voiddispatchMoveStarting(RecyclerView.ViewHolder item)

Method to be called by subclasses when a move animation is being started.

public final voiddispatchRemoveFinished(RecyclerView.ViewHolder item)

Method to be called by subclasses when a remove animation is done.

public final voiddispatchRemoveStarting(RecyclerView.ViewHolder item)

Method to be called by subclasses when a remove animation is being started.

public booleangetSupportsChangeAnimations()

Returns whether this ItemAnimator supports animations of change events.

public voidonAddFinished(RecyclerView.ViewHolder item)

Called when an add animation has ended on the given ViewHolder.

public voidonAddStarting(RecyclerView.ViewHolder item)

Called when an add animation is being started on the given ViewHolder.

public voidonChangeFinished(RecyclerView.ViewHolder item, boolean oldItem)

Called when a change animation has ended on the given ViewHolder.

public voidonChangeStarting(RecyclerView.ViewHolder item, boolean oldItem)

Called when a change animation is being started on the given ViewHolder.

public voidonMoveFinished(RecyclerView.ViewHolder item)

Called when a move animation has ended on the given ViewHolder.

public voidonMoveStarting(RecyclerView.ViewHolder item)

Called when a move animation is being started on the given ViewHolder.

public voidonRemoveFinished(RecyclerView.ViewHolder item)

Called when a remove animation has ended on the given ViewHolder.

public voidonRemoveStarting(RecyclerView.ViewHolder item)

Called when a remove animation is being started on the given ViewHolder.

public voidsetSupportsChangeAnimations(boolean supportsChangeAnimations)

Sets whether this ItemAnimator supports animations of item change events.

from RecyclerView.ItemAnimatorcanReuseUpdatedViewHolder, dispatchAnimationFinished, dispatchAnimationsFinished, dispatchAnimationStarted, endAnimation, endAnimations, getAddDuration, getChangeDuration, getMoveDuration, getRemoveDuration, isRunning, isRunning, obtainHolderInfo, onAnimationFinished, onAnimationStarted, recordPostLayoutInformation, recordPreLayoutInformation, runPendingAnimations, setAddDuration, setChangeDuration, setMoveDuration, setRemoveDuration
from java.lang.Objectclone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

Constructors

public SimpleItemAnimator()

Methods

public boolean getSupportsChangeAnimations()

Returns whether this ItemAnimator supports animations of change events.

Returns:

true if change animations are supported, false otherwise

public void setSupportsChangeAnimations(boolean supportsChangeAnimations)

Sets whether this ItemAnimator supports animations of item change events. If you set this property to false, actions on the data set which change the contents of items will not be animated. What those animations do is left up to the discretion of the ItemAnimator subclass, in its SimpleItemAnimator.animateChange(RecyclerView.ViewHolder, RecyclerView.ViewHolder, int, int, int, int) implementation. The value of this property is true by default.

Parameters:

supportsChangeAnimations: true if change animations are supported by this ItemAnimator, false otherwise. If the property is false, the ItemAnimator will not receive a call to SimpleItemAnimator.animateChange(RecyclerView.ViewHolder, RecyclerView.ViewHolder, int, int, int, int) when changes occur.

See also: RecyclerView.Adapter.notifyItemChanged(int), RecyclerView.Adapter.notifyItemRangeChanged(int, int)

public boolean canReuseUpdatedViewHolder(RecyclerView.ViewHolder viewHolder)

Returns:

True if change animations are not supported or the ViewHolder is invalid, false otherwise.

See also: SimpleItemAnimator.setSupportsChangeAnimations(boolean)

public abstract boolean animateDisappearance(RecyclerView.ViewHolder viewHolder, RecyclerView.ItemAnimator.ItemHolderInfo preLayoutInfo, RecyclerView.ItemAnimator.ItemHolderInfo postLayoutInfo)

Called by the RecyclerView when a ViewHolder has disappeared from the layout.

This means that the View was a child of the LayoutManager when layout started but has been removed by the LayoutManager. It might have been removed from the adapter or simply become invisible due to other factors. You can distinguish these two cases by checking the change flags that were passed to RecyclerView.ItemAnimator.

Note that when a ViewHolder both changes and disappears in the same layout pass, the animation callback method which will be called by the RecyclerView depends on the ItemAnimator's decision whether to re-use the same ViewHolder or not, and also the LayoutManager's decision whether to layout the changed version of a disappearing ViewHolder or not. RecyclerView will call animateChange instead of animateDisappearance if and only if the ItemAnimator returns false from canReuseUpdatedViewHolder and the LayoutManager lays out a new disappearing view that holds the updated information. Built-in LayoutManagers try to avoid laying out updated versions of disappearing views.

If LayoutManager supports predictive animations, it might provide a target disappear location for the View by laying it out in that location. When that happens, RecyclerView will call RecyclerView.ItemAnimator and the response of that call will be passed to this method as the postLayoutInfo.

ItemAnimator must call RecyclerView.ItemAnimator when the animation is complete (or instantly call RecyclerView.ItemAnimator if it decides not to animate the view).

Parameters:

viewHolder: The ViewHolder which should be animated
preLayoutInfo: The information that was returned from RecyclerView.ItemAnimator.
postLayoutInfo: The information that was returned from RecyclerView.ItemAnimator. Might be null if the LayoutManager did not layout the item.

Returns:

true if a later call to RecyclerView.ItemAnimator.runPendingAnimations() is requested, false otherwise.

public abstract boolean animateAppearance(RecyclerView.ViewHolder viewHolder, RecyclerView.ItemAnimator.ItemHolderInfo preLayoutInfo, RecyclerView.ItemAnimator.ItemHolderInfo postLayoutInfo)

Called by the RecyclerView when a ViewHolder is added to the layout.

In detail, this means that the ViewHolder was not a child when the layout started but has been added by the LayoutManager. It might be newly added to the adapter or simply become visible due to other factors.

ItemAnimator must call RecyclerView.ItemAnimator when the animation is complete (or instantly call RecyclerView.ItemAnimator if it decides not to animate the view).

Parameters:

viewHolder: The ViewHolder which should be animated
preLayoutInfo: The information that was returned from RecyclerView.ItemAnimator. Might be null if Item was just added to the adapter or LayoutManager does not support predictive animations or it could not predict that this ViewHolder will become visible.
postLayoutInfo: The information that was returned from RecyclerView.ItemAnimator.

Returns:

true if a later call to RecyclerView.ItemAnimator.runPendingAnimations() is requested, false otherwise.

public abstract boolean animatePersistence(RecyclerView.ViewHolder viewHolder, RecyclerView.ItemAnimator.ItemHolderInfo preLayoutInfo, RecyclerView.ItemAnimator.ItemHolderInfo postLayoutInfo)

Called by the RecyclerView when a ViewHolder is present in both before and after the layout and RecyclerView has not received a RecyclerView.Adapter.notifyItemChanged(int) call for it or a RecyclerView.Adapter.notifyDataSetChanged() call.

This ViewHolder still represents the same data that it was representing when the layout started but its position / size may be changed by the LayoutManager.

If the Item's layout position didn't change, RecyclerView still calls this method because it does not track this information (or does not necessarily know that an animation is not required). Your ItemAnimator should handle this case and if there is nothing to animate, it should call RecyclerView.ItemAnimator and return false.

ItemAnimator must call RecyclerView.ItemAnimator when the animation is complete (or instantly call RecyclerView.ItemAnimator if it decides not to animate the view).

Parameters:

viewHolder: The ViewHolder which should be animated
preLayoutInfo: The information that was returned from RecyclerView.ItemAnimator.
postLayoutInfo: The information that was returned from RecyclerView.ItemAnimator.

Returns:

true if a later call to RecyclerView.ItemAnimator.runPendingAnimations() is requested, false otherwise.

public abstract boolean animateChange(RecyclerView.ViewHolder oldHolder, RecyclerView.ViewHolder newHolder, RecyclerView.ItemAnimator.ItemHolderInfo preLayoutInfo, RecyclerView.ItemAnimator.ItemHolderInfo postLayoutInfo)

Called by the RecyclerView when an adapter item is present both before and after the layout and RecyclerView has received a RecyclerView.Adapter.notifyItemChanged(int) call for it. This method may also be called when RecyclerView.Adapter.notifyDataSetChanged() is called and adapter has stable ids so that RecyclerView could still rebind views to the same ViewHolders. If viewType changes when RecyclerView.Adapter.notifyDataSetChanged() is called, this method will not be called, instead, RecyclerView.ItemAnimator will be called for the new ViewHolder and the old one will be recycled.

If this method is called due to a RecyclerView.Adapter.notifyDataSetChanged() call, there is a good possibility that item contents didn't really change but it is rebound from the adapter. DefaultItemAnimator will skip animating the View if its location on the screen didn't change and your animator should handle this case as well and avoid creating unnecessary animations.

When an item is updated, ItemAnimator has a chance to ask RecyclerView to keep the previous presentation of the item as-is and supply a new ViewHolder for the updated presentation (see: RecyclerView.ItemAnimator. This is useful if you don't know the contents of the Item and would like to cross-fade the old and the new one (DefaultItemAnimator uses this technique).

When you are writing a custom item animator for your layout, it might be more performant and elegant to re-use the same ViewHolder and animate the content changes manually.

When RecyclerView.Adapter.notifyItemChanged(int) is called, the Item's view type may change. If the Item's view type has changed or ItemAnimator returned false for this ViewHolder when RecyclerView.ItemAnimator was called, the oldHolder and newHolder will be different ViewHolder instances which represent the same Item. In that case, only the new ViewHolder is visible to the LayoutManager but RecyclerView keeps old ViewHolder attached for animations.

ItemAnimator must call RecyclerView.ItemAnimator for each distinct ViewHolder when their animation is complete (or instantly call RecyclerView.ItemAnimator if it decides not to animate the view).

If oldHolder and newHolder are the same instance, you should call RecyclerView.ItemAnimator only once.

Note that when a ViewHolder both changes and disappears in the same layout pass, the animation callback method which will be called by the RecyclerView depends on the ItemAnimator's decision whether to re-use the same ViewHolder or not, and also the LayoutManager's decision whether to layout the changed version of a disappearing ViewHolder or not. RecyclerView will call animateChange instead of animateDisappearance if and only if the ItemAnimator returns false from canReuseUpdatedViewHolder and the LayoutManager lays out a new disappearing view that holds the updated information. Built-in LayoutManagers try to avoid laying out updated versions of disappearing views.

Parameters:

oldHolder: The ViewHolder before the layout is started, might be the same instance with newHolder.
newHolder: The ViewHolder after the layout is finished, might be the same instance with oldHolder.
preLayoutInfo: The information that was returned from RecyclerView.ItemAnimator.
postLayoutInfo: The information that was returned from RecyclerView.ItemAnimator.

Returns:

true if a later call to RecyclerView.ItemAnimator.runPendingAnimations() is requested, false otherwise.

public abstract boolean animateRemove(RecyclerView.ViewHolder holder)

Called when an item is removed from the RecyclerView. Implementors can choose whether and how to animate that change, but must always call SimpleItemAnimator.dispatchRemoveFinished(RecyclerView.ViewHolder) when done, either immediately (if no animation will occur) or after the animation actually finishes. The return value indicates whether an animation has been set up and whether the ItemAnimator's RecyclerView.ItemAnimator.runPendingAnimations() method should be called at the next opportunity. This mechanism allows ItemAnimator to set up individual animations as separate calls to animateAdd(), animateMove(), animateRemove(), and SimpleItemAnimator.animateChange(RecyclerView.ViewHolder, RecyclerView.ViewHolder, int, int, int, int) come in one by one, then start the animations together in the later call to RecyclerView.ItemAnimator.runPendingAnimations().

This method may also be called for disappearing items which continue to exist in the RecyclerView, but for which the system does not have enough information to animate them out of view. In that case, the default animation for removing items is run on those items as well.

Parameters:

holder: The item that is being removed.

Returns:

true if a later call to RecyclerView.ItemAnimator.runPendingAnimations() is requested, false otherwise.

public abstract boolean animateAdd(RecyclerView.ViewHolder holder)

Called when an item is added to the RecyclerView. Implementors can choose whether and how to animate that change, but must always call SimpleItemAnimator.dispatchAddFinished(RecyclerView.ViewHolder) when done, either immediately (if no animation will occur) or after the animation actually finishes. The return value indicates whether an animation has been set up and whether the ItemAnimator's RecyclerView.ItemAnimator.runPendingAnimations() method should be called at the next opportunity. This mechanism allows ItemAnimator to set up individual animations as separate calls to animateAdd(), animateMove(), animateRemove(), and SimpleItemAnimator.animateChange(RecyclerView.ViewHolder, RecyclerView.ViewHolder, int, int, int, int) come in one by one, then start the animations together in the later call to RecyclerView.ItemAnimator.runPendingAnimations().

This method may also be called for appearing items which were already in the RecyclerView, but for which the system does not have enough information to animate them into view. In that case, the default animation for adding items is run on those items as well.

Parameters:

holder: The item that is being added.

Returns:

true if a later call to RecyclerView.ItemAnimator.runPendingAnimations() is requested, false otherwise.

public abstract boolean animateMove(RecyclerView.ViewHolder holder, int fromX, int fromY, int toX, int toY)

Called when an item is moved in the RecyclerView. Implementors can choose whether and how to animate that change, but must always call SimpleItemAnimator.dispatchMoveFinished(RecyclerView.ViewHolder) when done, either immediately (if no animation will occur) or after the animation actually finishes. The return value indicates whether an animation has been set up and whether the ItemAnimator's RecyclerView.ItemAnimator.runPendingAnimations() method should be called at the next opportunity. This mechanism allows ItemAnimator to set up individual animations as separate calls to animateAdd(), animateMove(), animateRemove(), and SimpleItemAnimator.animateChange(RecyclerView.ViewHolder, RecyclerView.ViewHolder, int, int, int, int) come in one by one, then start the animations together in the later call to RecyclerView.ItemAnimator.runPendingAnimations().

Parameters:

holder: The item that is being moved.
fromX: x coordinate from which to start animation.
fromY: y coordinate from which to start animation.
toX: x coordinate at which to end animation.
toY: y coordinate at which to end animation.

Returns:

true if a later call to RecyclerView.ItemAnimator.runPendingAnimations() is requested, false otherwise.

public abstract boolean animateChange(RecyclerView.ViewHolder oldHolder, RecyclerView.ViewHolder newHolder, int fromLeft, int fromTop, int toLeft, int toTop)

Called when an item is changed in the RecyclerView, as indicated by a call to RecyclerView.Adapter.notifyItemChanged(int) or RecyclerView.Adapter.notifyItemRangeChanged(int, int).

Implementers can choose whether and how to animate changes, but must always call SimpleItemAnimator.dispatchChangeFinished(RecyclerView.ViewHolder, boolean) for each non-null distinct ViewHolder, either immediately (if no animation will occur) or after the animation actually finishes. If the oldHolder is the same ViewHolder as the newHolder, you must call SimpleItemAnimator.dispatchChangeFinished(RecyclerView.ViewHolder, boolean) once and only once. In that case, the second parameter of dispatchChangeFinished is ignored.

The return value indicates whether an animation has been set up and whether the ItemAnimator's RecyclerView.ItemAnimator.runPendingAnimations() method should be called at the next opportunity. This mechanism allows ItemAnimator to set up individual animations as separate calls to animateAdd(), animateMove(), animateRemove(), and SimpleItemAnimator.animateChange(RecyclerView.ViewHolder, RecyclerView.ViewHolder, int, int, int, int) come in one by one, then start the animations together in the later call to RecyclerView.ItemAnimator.runPendingAnimations().

Parameters:

oldHolder: The original item that changed.
newHolder: The new item that was created with the changed content. Might be null
fromLeft: Left of the old view holder
fromTop: Top of the old view holder
toLeft: Left of the new view holder
toTop: Top of the new view holder

Returns:

true if a later call to RecyclerView.ItemAnimator.runPendingAnimations() is requested, false otherwise.

public final void dispatchRemoveFinished(RecyclerView.ViewHolder item)

Method to be called by subclasses when a remove animation is done.

Parameters:

item: The item which has been removed

See also: RecyclerView.ItemAnimator.animateDisappearance(RecyclerView.ViewHolder, RecyclerView.ItemAnimator.ItemHolderInfo, RecyclerView.ItemAnimator.ItemHolderInfo)

public final void dispatchMoveFinished(RecyclerView.ViewHolder item)

Method to be called by subclasses when a move animation is done.

Parameters:

item: The item which has been moved

See also: RecyclerView.ItemAnimator.animateDisappearance(RecyclerView.ViewHolder, RecyclerView.ItemAnimator.ItemHolderInfo, RecyclerView.ItemAnimator.ItemHolderInfo), RecyclerView.ItemAnimator.animatePersistence(RecyclerView.ViewHolder, RecyclerView.ItemAnimator.ItemHolderInfo, RecyclerView.ItemAnimator.ItemHolderInfo), RecyclerView.ItemAnimator.animateAppearance(RecyclerView.ViewHolder, RecyclerView.ItemAnimator.ItemHolderInfo, RecyclerView.ItemAnimator.ItemHolderInfo)

public final void dispatchAddFinished(RecyclerView.ViewHolder item)

Method to be called by subclasses when an add animation is done.

Parameters:

item: The item which has been added

public final void dispatchChangeFinished(RecyclerView.ViewHolder item, boolean oldItem)

Method to be called by subclasses when a change animation is done.

Parameters:

item: The item which has been changed (this method must be called for each non-null ViewHolder passed into SimpleItemAnimator.animateChange(RecyclerView.ViewHolder, RecyclerView.ViewHolder, int, int, int, int)).
oldItem: true if this is the old item that was changed, false if it is the new item that replaced the old item.

See also: SimpleItemAnimator.animateChange(RecyclerView.ViewHolder, RecyclerView.ViewHolder, int, int, int, int)

public final void dispatchRemoveStarting(RecyclerView.ViewHolder item)

Method to be called by subclasses when a remove animation is being started.

Parameters:

item: The item being removed

public final void dispatchMoveStarting(RecyclerView.ViewHolder item)

Method to be called by subclasses when a move animation is being started.

Parameters:

item: The item being moved

public final void dispatchAddStarting(RecyclerView.ViewHolder item)

Method to be called by subclasses when an add animation is being started.

Parameters:

item: The item being added

public final void dispatchChangeStarting(RecyclerView.ViewHolder item, boolean oldItem)

Method to be called by subclasses when a change animation is being started.

Parameters:

item: The item which has been changed (this method must be called for each non-null ViewHolder passed into SimpleItemAnimator.animateChange(RecyclerView.ViewHolder, RecyclerView.ViewHolder, int, int, int, int)).
oldItem: true if this is the old item that was changed, false if it is the new item that replaced the old item.

public void onRemoveStarting(RecyclerView.ViewHolder item)

Called when a remove animation is being started on the given ViewHolder. The default implementation does nothing. Subclasses may wish to override this method to handle any ViewHolder-specific operations linked to animation lifecycles.

Parameters:

item: The ViewHolder being animated.

public void onRemoveFinished(RecyclerView.ViewHolder item)

Called when a remove animation has ended on the given ViewHolder. The default implementation does nothing. Subclasses may wish to override this method to handle any ViewHolder-specific operations linked to animation lifecycles.

Parameters:

item: The ViewHolder being animated.

public void onAddStarting(RecyclerView.ViewHolder item)

Called when an add animation is being started on the given ViewHolder. The default implementation does nothing. Subclasses may wish to override this method to handle any ViewHolder-specific operations linked to animation lifecycles.

Parameters:

item: The ViewHolder being animated.

public void onAddFinished(RecyclerView.ViewHolder item)

Called when an add animation has ended on the given ViewHolder. The default implementation does nothing. Subclasses may wish to override this method to handle any ViewHolder-specific operations linked to animation lifecycles.

Parameters:

item: The ViewHolder being animated.

public void onMoveStarting(RecyclerView.ViewHolder item)

Called when a move animation is being started on the given ViewHolder. The default implementation does nothing. Subclasses may wish to override this method to handle any ViewHolder-specific operations linked to animation lifecycles.

Parameters:

item: The ViewHolder being animated.

public void onMoveFinished(RecyclerView.ViewHolder item)

Called when a move animation has ended on the given ViewHolder. The default implementation does nothing. Subclasses may wish to override this method to handle any ViewHolder-specific operations linked to animation lifecycles.

Parameters:

item: The ViewHolder being animated.

public void onChangeStarting(RecyclerView.ViewHolder item, boolean oldItem)

Called when a change animation is being started on the given ViewHolder. The default implementation does nothing. Subclasses may wish to override this method to handle any ViewHolder-specific operations linked to animation lifecycles.

Parameters:

item: The ViewHolder being animated.
oldItem: true if this is the old item that was changed, false if it is the new item that replaced the old item.

public void onChangeFinished(RecyclerView.ViewHolder item, boolean oldItem)

Called when a change animation has ended on the given ViewHolder. The default implementation does nothing. Subclasses may wish to override this method to handle any ViewHolder-specific operations linked to animation lifecycles.

Parameters:

item: The ViewHolder being animated.
oldItem: true if this is the old item that was changed, false if it is the new item that replaced the old item.

Source

/*
 * Copyright 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package androidx.recyclerview.widget;

import android.annotation.SuppressLint;
import android.util.Log;
import android.view.View;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

/**
 * A wrapper class for ItemAnimator that records View bounds and decides whether it should run
 * move, change, add or remove animations. This class also replicates the original ItemAnimator
 * API.
 * <p>
 * It uses {@link RecyclerView.ItemAnimator.ItemHolderInfo} to track the bounds information of
 * the Views. If you would like to extend this class, you can override {@link #obtainHolderInfo()}
 * method to provide your own info class that extends
 * {@link RecyclerView.ItemAnimator.ItemHolderInfo}.
 */
public abstract class SimpleItemAnimator extends RecyclerView.ItemAnimator {

    private static final boolean DEBUG = false;

    private static final String TAG = "SimpleItemAnimator";

    boolean mSupportsChangeAnimations = true;

    /**
     * Returns whether this ItemAnimator supports animations of change events.
     *
     * @return true if change animations are supported, false otherwise
     */
    @SuppressWarnings("unused")
    public boolean getSupportsChangeAnimations() {
        return mSupportsChangeAnimations;
    }

    /**
     * Sets whether this ItemAnimator supports animations of item change events.
     * If you set this property to false, actions on the data set which change the
     * contents of items will not be animated. What those animations do is left
     * up to the discretion of the ItemAnimator subclass, in its
     * {@link #animateChange(RecyclerView.ViewHolder, RecyclerView.ViewHolder, int, int, int, int)} implementation.
     * The value of this property is true by default.
     *
     * @param supportsChangeAnimations true if change animations are supported by
     *                                 this ItemAnimator, false otherwise. If the property is false,
     *                                 the ItemAnimator
     *                                 will not receive a call to
     *                                 {@link #animateChange(RecyclerView.ViewHolder, RecyclerView.ViewHolder, int, int, int,
     *                                 int)} when changes occur.
     * @see RecyclerView.Adapter#notifyItemChanged(int)
     * @see RecyclerView.Adapter#notifyItemRangeChanged(int, int)
     */
    public void setSupportsChangeAnimations(boolean supportsChangeAnimations) {
        mSupportsChangeAnimations = supportsChangeAnimations;
    }

    /**
     * {@inheritDoc}
     *
     * @return True if change animations are not supported or the ViewHolder is invalid,
     * false otherwise.
     *
     * @see #setSupportsChangeAnimations(boolean)
     */
    @Override
    public boolean canReuseUpdatedViewHolder(@NonNull RecyclerView.ViewHolder viewHolder) {
        return !mSupportsChangeAnimations || viewHolder.isInvalid();
    }

    @Override
    public boolean animateDisappearance(@NonNull RecyclerView.ViewHolder viewHolder,
            @NonNull ItemHolderInfo preLayoutInfo, @Nullable ItemHolderInfo postLayoutInfo) {
        int oldLeft = preLayoutInfo.left;
        int oldTop = preLayoutInfo.top;
        View disappearingItemView = viewHolder.itemView;
        int newLeft = postLayoutInfo == null ? disappearingItemView.getLeft() : postLayoutInfo.left;
        int newTop = postLayoutInfo == null ? disappearingItemView.getTop() : postLayoutInfo.top;
        if (!viewHolder.isRemoved() && (oldLeft != newLeft || oldTop != newTop)) {
            disappearingItemView.layout(newLeft, newTop,
                    newLeft + disappearingItemView.getWidth(),
                    newTop + disappearingItemView.getHeight());
            if (DEBUG) {
                Log.d(TAG, "DISAPPEARING: " + viewHolder + " with view " + disappearingItemView);
            }
            return animateMove(viewHolder, oldLeft, oldTop, newLeft, newTop);
        } else {
            if (DEBUG) {
                Log.d(TAG, "REMOVED: " + viewHolder + " with view " + disappearingItemView);
            }
            return animateRemove(viewHolder);
        }
    }

    @Override
    public boolean animateAppearance(@NonNull RecyclerView.ViewHolder viewHolder,
            @Nullable ItemHolderInfo preLayoutInfo, @NonNull ItemHolderInfo postLayoutInfo) {
        if (preLayoutInfo != null && (preLayoutInfo.left != postLayoutInfo.left
                || preLayoutInfo.top != postLayoutInfo.top)) {
            // slide items in if before/after locations differ
            if (DEBUG) {
                Log.d(TAG, "APPEARING: " + viewHolder + " with view " + viewHolder);
            }
            return animateMove(viewHolder, preLayoutInfo.left, preLayoutInfo.top,
                    postLayoutInfo.left, postLayoutInfo.top);
        } else {
            if (DEBUG) {
                Log.d(TAG, "ADDED: " + viewHolder + " with view " + viewHolder);
            }
            return animateAdd(viewHolder);
        }
    }

    @Override
    public boolean animatePersistence(@NonNull RecyclerView.ViewHolder viewHolder,
            @NonNull ItemHolderInfo preLayoutInfo, @NonNull ItemHolderInfo postLayoutInfo) {
        if (preLayoutInfo.left != postLayoutInfo.left || preLayoutInfo.top != postLayoutInfo.top) {
            if (DEBUG) {
                Log.d(TAG, "PERSISTENT: " + viewHolder
                        + " with view " + viewHolder.itemView);
            }
            return animateMove(viewHolder,
                    preLayoutInfo.left, preLayoutInfo.top, postLayoutInfo.left, postLayoutInfo.top);
        }
        dispatchMoveFinished(viewHolder);
        return false;
    }

    @Override
    public boolean animateChange(@NonNull RecyclerView.ViewHolder oldHolder,
            @NonNull RecyclerView.ViewHolder newHolder, @NonNull ItemHolderInfo preLayoutInfo,
            @NonNull ItemHolderInfo postLayoutInfo) {
        if (DEBUG) {
            Log.d(TAG, "CHANGED: " + oldHolder + " with view " + oldHolder.itemView);
        }
        final int fromLeft = preLayoutInfo.left;
        final int fromTop = preLayoutInfo.top;
        final int toLeft, toTop;
        if (newHolder.shouldIgnore()) {
            toLeft = preLayoutInfo.left;
            toTop = preLayoutInfo.top;
        } else {
            toLeft = postLayoutInfo.left;
            toTop = postLayoutInfo.top;
        }
        return animateChange(oldHolder, newHolder, fromLeft, fromTop, toLeft, toTop);
    }

    /**
     * Called when an item is removed from the RecyclerView. Implementors can choose
     * whether and how to animate that change, but must always call
     * {@link #dispatchRemoveFinished(RecyclerView.ViewHolder)} when done, either
     * immediately (if no animation will occur) or after the animation actually finishes.
     * The return value indicates whether an animation has been set up and whether the
     * ItemAnimator's {@link #runPendingAnimations()} method should be called at the
     * next opportunity. This mechanism allows ItemAnimator to set up individual animations
     * as separate calls to {@link #animateAdd(RecyclerView.ViewHolder) animateAdd()},
     * {@link #animateMove(RecyclerView.ViewHolder, int, int, int, int) animateMove()},
     * {@link #animateRemove(RecyclerView.ViewHolder) animateRemove()}, and
     * {@link #animateChange(RecyclerView.ViewHolder, RecyclerView.ViewHolder, int, int, int, int)} come in one by one,
     * then start the animations together in the later call to {@link #runPendingAnimations()}.
     *
     * <p>This method may also be called for disappearing items which continue to exist in the
     * RecyclerView, but for which the system does not have enough information to animate
     * them out of view. In that case, the default animation for removing items is run
     * on those items as well.</p>
     *
     * @param holder The item that is being removed.
     * @return true if a later call to {@link #runPendingAnimations()} is requested,
     * false otherwise.
     */
    @SuppressLint("UnknownNullness") // b/240775049: Cannot annotate properly
    public abstract boolean animateRemove(RecyclerView.ViewHolder holder);

    /**
     * Called when an item is added to the RecyclerView. Implementors can choose
     * whether and how to animate that change, but must always call
     * {@link #dispatchAddFinished(RecyclerView.ViewHolder)} when done, either
     * immediately (if no animation will occur) or after the animation actually finishes.
     * The return value indicates whether an animation has been set up and whether the
     * ItemAnimator's {@link #runPendingAnimations()} method should be called at the
     * next opportunity. This mechanism allows ItemAnimator to set up individual animations
     * as separate calls to {@link #animateAdd(RecyclerView.ViewHolder) animateAdd()},
     * {@link #animateMove(RecyclerView.ViewHolder, int, int, int, int) animateMove()},
     * {@link #animateRemove(RecyclerView.ViewHolder) animateRemove()}, and
     * {@link #animateChange(RecyclerView.ViewHolder, RecyclerView.ViewHolder, int, int, int, int)} come in one by one,
     * then start the animations together in the later call to {@link #runPendingAnimations()}.
     *
     * <p>This method may also be called for appearing items which were already in the
     * RecyclerView, but for which the system does not have enough information to animate
     * them into view. In that case, the default animation for adding items is run
     * on those items as well.</p>
     *
     * @param holder The item that is being added.
     * @return true if a later call to {@link #runPendingAnimations()} is requested,
     * false otherwise.
     */
    @SuppressLint("UnknownNullness") // b/240775049: Cannot annotate properly
    public abstract boolean animateAdd(RecyclerView.ViewHolder holder);

    /**
     * Called when an item is moved in the RecyclerView. Implementors can choose
     * whether and how to animate that change, but must always call
     * {@link #dispatchMoveFinished(RecyclerView.ViewHolder)} when done, either
     * immediately (if no animation will occur) or after the animation actually finishes.
     * The return value indicates whether an animation has been set up and whether the
     * ItemAnimator's {@link #runPendingAnimations()} method should be called at the
     * next opportunity. This mechanism allows ItemAnimator to set up individual animations
     * as separate calls to {@link #animateAdd(RecyclerView.ViewHolder) animateAdd()},
     * {@link #animateMove(RecyclerView.ViewHolder, int, int, int, int) animateMove()},
     * {@link #animateRemove(RecyclerView.ViewHolder) animateRemove()}, and
     * {@link #animateChange(RecyclerView.ViewHolder, RecyclerView.ViewHolder, int, int, int, int)} come in one by one,
     * then start the animations together in the later call to {@link #runPendingAnimations()}.
     *
     * @param holder The item that is being moved.
     * @param fromX x coordinate from which to start animation.
     * @param fromY y coordinate from which to start animation.
     * @param toX x coordinate at which to end animation.
     * @param toY y coordinate at which to end animation.
     * @return true if a later call to {@link #runPendingAnimations()} is requested,
     * false otherwise.
     */
    @SuppressLint("UnknownNullness") // b/240775049: Cannot annotate properly
    public abstract boolean animateMove(RecyclerView.ViewHolder holder, int fromX, int fromY,
            int toX, int toY);

    /**
     * Called when an item is changed in the RecyclerView, as indicated by a call to
     * {@link RecyclerView.Adapter#notifyItemChanged(int)} or
     * {@link RecyclerView.Adapter#notifyItemRangeChanged(int, int)}.
     * <p>
     * Implementers can choose whether and how to animate changes, but must always call
     * {@link #dispatchChangeFinished(RecyclerView.ViewHolder, boolean)} for each non-null
     * distinct ViewHolder,
     * either immediately (if no animation will occur) or after the animation actually finishes.
     * If the {@code oldHolder} is the same ViewHolder as the {@code newHolder}, you must call
     * {@link #dispatchChangeFinished(RecyclerView.ViewHolder, boolean)} once and only once. In
     * that case, the
     * second parameter of {@code dispatchChangeFinished} is ignored.
     * <p>
     * The return value indicates whether an animation has been set up and whether the
     * ItemAnimator's {@link #runPendingAnimations()} method should be called at the
     * next opportunity. This mechanism allows ItemAnimator to set up individual animations
     * as separate calls to {@link #animateAdd(RecyclerView.ViewHolder) animateAdd()},
     * {@link #animateMove(RecyclerView.ViewHolder, int, int, int, int) animateMove()},
     * {@link #animateRemove(RecyclerView.ViewHolder) animateRemove()}, and
     * {@link #animateChange(RecyclerView.ViewHolder, RecyclerView.ViewHolder, int, int, int, int)} come in one by one,
     * then start the animations together in the later call to {@link #runPendingAnimations()}.
     *
     * @param oldHolder The original item that changed.
     * @param newHolder The new item that was created with the changed content. Might be null
     * @param fromLeft  Left of the old view holder
     * @param fromTop   Top of the old view holder
     * @param toLeft    Left of the new view holder
     * @param toTop     Top of the new view holder
     * @return true if a later call to {@link #runPendingAnimations()} is requested,
     * false otherwise.
     */
    @SuppressLint("UnknownNullness") // b/240775049: Cannot annotate properly
    public abstract boolean animateChange(RecyclerView.ViewHolder oldHolder,
            RecyclerView.ViewHolder newHolder, int fromLeft, int fromTop, int toLeft, int toTop);

    /**
     * Method to be called by subclasses when a remove animation is done.
     *
     * @param item The item which has been removed
     * @see RecyclerView.ItemAnimator#animateDisappearance(RecyclerView.ViewHolder, ItemHolderInfo,
     * ItemHolderInfo)
     */
    @SuppressLint("UnknownNullness") // b/240775049: Cannot annotate properly
    public final void dispatchRemoveFinished(RecyclerView.ViewHolder item) {
        onRemoveFinished(item);
        dispatchAnimationFinished(item);
    }

    /**
     * Method to be called by subclasses when a move animation is done.
     *
     * @param item The item which has been moved
     * @see RecyclerView.ItemAnimator#animateDisappearance(RecyclerView.ViewHolder, ItemHolderInfo,
     * ItemHolderInfo)
     * @see RecyclerView.ItemAnimator#animatePersistence(RecyclerView.ViewHolder, ItemHolderInfo, ItemHolderInfo)
     * @see RecyclerView.ItemAnimator#animateAppearance(RecyclerView.ViewHolder, ItemHolderInfo, ItemHolderInfo)
     */
    @SuppressLint("UnknownNullness") // b/240775049: Cannot annotate properly
    public final void dispatchMoveFinished(RecyclerView.ViewHolder item) {
        onMoveFinished(item);
        dispatchAnimationFinished(item);
    }

    /**
     * Method to be called by subclasses when an add animation is done.
     *
     * @param item The item which has been added
     */
    @SuppressLint("UnknownNullness") // b/240775049: Cannot annotate properly
    public final void dispatchAddFinished(RecyclerView.ViewHolder item) {
        onAddFinished(item);
        dispatchAnimationFinished(item);
    }

    /**
     * Method to be called by subclasses when a change animation is done.
     *
     * @param item    The item which has been changed (this method must be called for
     *                each non-null ViewHolder passed into
     *                {@link #animateChange(RecyclerView.ViewHolder, RecyclerView.ViewHolder, int, int, int, int)}).
     * @param oldItem true if this is the old item that was changed, false if
     *                it is the new item that replaced the old item.
     * @see #animateChange(RecyclerView.ViewHolder, RecyclerView.ViewHolder, int, int, int, int)
     */
    @SuppressLint("UnknownNullness") // b/240775049: Cannot annotate properly
    public final void dispatchChangeFinished(RecyclerView.ViewHolder item, boolean oldItem) {
        onChangeFinished(item, oldItem);
        dispatchAnimationFinished(item);
    }

    /**
     * Method to be called by subclasses when a remove animation is being started.
     *
     * @param item The item being removed
     */
    @SuppressLint("UnknownNullness") // b/240775049: Cannot annotate properly
    public final void dispatchRemoveStarting(RecyclerView.ViewHolder item) {
        onRemoveStarting(item);
    }

    /**
     * Method to be called by subclasses when a move animation is being started.
     *
     * @param item The item being moved
     */
    @SuppressLint("UnknownNullness") // b/240775049: Cannot annotate properly
    public final void dispatchMoveStarting(RecyclerView.ViewHolder item) {
        onMoveStarting(item);
    }

    /**
     * Method to be called by subclasses when an add animation is being started.
     *
     * @param item The item being added
     */
    @SuppressLint("UnknownNullness") // b/240775049: Cannot annotate properly
    public final void dispatchAddStarting(RecyclerView.ViewHolder item) {
        onAddStarting(item);
    }

    /**
     * Method to be called by subclasses when a change animation is being started.
     *
     * @param item    The item which has been changed (this method must be called for
     *                each non-null ViewHolder passed into
     *                {@link #animateChange(RecyclerView.ViewHolder, RecyclerView.ViewHolder, int, int, int, int)}).
     * @param oldItem true if this is the old item that was changed, false if
     *                it is the new item that replaced the old item.
     */
    @SuppressLint("UnknownNullness") // b/240775049: Cannot annotate properly
    public final void dispatchChangeStarting(RecyclerView.ViewHolder item, boolean oldItem) {
        onChangeStarting(item, oldItem);
    }

    /**
     * Called when a remove animation is being started on the given ViewHolder.
     * The default implementation does nothing. Subclasses may wish to override
     * this method to handle any ViewHolder-specific operations linked to animation
     * lifecycles.
     *
     * @param item The ViewHolder being animated.
     */
    @SuppressLint("UnknownNullness") // b/240775049: Cannot annotate properly
    @SuppressWarnings("UnusedParameters")
    public void onRemoveStarting(RecyclerView.ViewHolder item) {
    }

    /**
     * Called when a remove animation has ended on the given ViewHolder.
     * The default implementation does nothing. Subclasses may wish to override
     * this method to handle any ViewHolder-specific operations linked to animation
     * lifecycles.
     *
     * @param item The ViewHolder being animated.
     */
    @SuppressLint("UnknownNullness") // b/240775049: Cannot annotate properly
    public void onRemoveFinished(RecyclerView.ViewHolder item) {
    }

    /**
     * Called when an add animation is being started on the given ViewHolder.
     * The default implementation does nothing. Subclasses may wish to override
     * this method to handle any ViewHolder-specific operations linked to animation
     * lifecycles.
     *
     * @param item The ViewHolder being animated.
     */
    @SuppressWarnings("UnusedParameters")
    @SuppressLint("UnknownNullness") // b/240775049: Cannot annotate properly
    public void onAddStarting(RecyclerView.ViewHolder item) {
    }

    /**
     * Called when an add animation has ended on the given ViewHolder.
     * The default implementation does nothing. Subclasses may wish to override
     * this method to handle any ViewHolder-specific operations linked to animation
     * lifecycles.
     *
     * @param item The ViewHolder being animated.
     */
    @SuppressLint("UnknownNullness") // b/240775049: Cannot annotate properly
    public void onAddFinished(RecyclerView.ViewHolder item) {
    }

    /**
     * Called when a move animation is being started on the given ViewHolder.
     * The default implementation does nothing. Subclasses may wish to override
     * this method to handle any ViewHolder-specific operations linked to animation
     * lifecycles.
     *
     * @param item The ViewHolder being animated.
     */
    @SuppressWarnings("UnusedParameters")
    @SuppressLint("UnknownNullness") // b/240775049: Cannot annotate properly
    public void onMoveStarting(RecyclerView.ViewHolder item) {
    }

    /**
     * Called when a move animation has ended on the given ViewHolder.
     * The default implementation does nothing. Subclasses may wish to override
     * this method to handle any ViewHolder-specific operations linked to animation
     * lifecycles.
     *
     * @param item The ViewHolder being animated.
     */
    @SuppressLint("UnknownNullness") // b/240775049: Cannot annotate properly
    public void onMoveFinished(RecyclerView.ViewHolder item) {
    }

    /**
     * Called when a change animation is being started on the given ViewHolder.
     * The default implementation does nothing. Subclasses may wish to override
     * this method to handle any ViewHolder-specific operations linked to animation
     * lifecycles.
     *
     * @param item    The ViewHolder being animated.
     * @param oldItem true if this is the old item that was changed, false if
     *                it is the new item that replaced the old item.
     */
    @SuppressLint("UnknownNullness") // b/240775049: Cannot annotate properly
    @SuppressWarnings("UnusedParameters")
    public void onChangeStarting(RecyclerView.ViewHolder item, boolean oldItem) {
    }

    /**
     * Called when a change animation has ended on the given ViewHolder.
     * The default implementation does nothing. Subclasses may wish to override
     * this method to handle any ViewHolder-specific operations linked to animation
     * lifecycles.
     *
     * @param item    The ViewHolder being animated.
     * @param oldItem true if this is the old item that was changed, false if
     *                it is the new item that replaced the old item.
     */
    @SuppressLint("UnknownNullness") // b/240775049: Cannot annotate properly
    public void onChangeFinished(RecyclerView.ViewHolder item, boolean oldItem) {
    }
}