RecyclerView predictive item animations not working (APPEARING)
Asked Answered
M

2

6

I have a RecyclerView with GridLayoutManager (support lib v7). I update adapter and make notifyItemMoved. If the item source position is on the screen and the destination position is on the screen as well - "move animation" is played. In case if the item was at position out of the screen(position 1000, or any other far from viewport) and moved into viewport it will appear with "fade in animation".

Looks like predictive item animations are not working despite on the fact supportsPredictiveItemAnimations() returns true. Am I doing something wrong? Should I override some methods to enable it?

I was reading the source code of RecyclerView, and in javadoc of the dispatchLayout method is written like:

  • PERSISTENT views are moved ({@link ItemAnimator#animateMove(ViewHolder, int, int, int, int)})
  • REMOVED views are removed ({@link ItemAnimator#animateRemove(ViewHolder)})
  • ADDED views are added ({@link ItemAnimator#animateAdd(ViewHolder)})
  • DISAPPEARING views are moved off screen
  • APPEARING views are moved on screen

Nevertheless ItemAnimator doesn't distinguish ADDED and APPEARING. Is it possible fix predictife animations or at least make APPEARING animation look like "move from outside of the screen animation" lefting ADDED animation as is?

Mentholated answered 21/3, 2015 at 0:39 Comment(3)
I thought appearing was used for view visibility changes, rather than adding to the adapter?Pasho
@Pasho Here is the javadoc, you can check: sourceMentholated
Ah, I see. I remember reading an article that discussed the fade-in problem. See wiresareobsolete.com/2015/02/recyclerview-layoutmanager-3 for details.Pasho
G
0

You can try to override getExtraLayoutSpace(RecyclerView.State state) of LinearLayoutManager to provide the manager extra space for predictive animations.

example :

@Override
protected int getExtraLayoutSpace(RecyclerView.State state) {
    return getHeight(); // add extra page for better predictive animations
}

The extra space will be added either at the start or at the end depending on the previous scroll delta of your scroll view. You can take a look at the implementation of onLayoutChildren of LinearLayoutManager for more details.

Globuliferous answered 17/11, 2015 at 11:30 Comment(0)
A
0

I had same problem. Check if you have set ItemAnimator. Predictive animation depends on it, so if you are going to use TransitionManager instead, then create empty ItemAnimator to enable predictive animations.

You can check source code (LinearLayoutManager: group: 'com.android.support', name: 'recyclerview-v7', version: '27.0.2').

Lines 700-703:

if (!state.willRunPredictiveAnimations() ||  getChildCount() == 0 || state.isPreLayout()
            || !supportsPredictiveItemAnimations()) {
        return;
    }

state.willRunPredictiveAnimations() - will return false if ItemAnimator is null.

EmptyItemAnimator.java

public class EmptyItemAnimator extends RecyclerView.ItemAnimator {
@Override
public boolean isRunning() {
    return false;
}

@Override
public void endAnimations() {}

@Override
public boolean animatePersistence(@NonNull RecyclerView.ViewHolder viewHolder, @NonNull ItemHolderInfo preLayoutInfo, @NonNull ItemHolderInfo postLayoutInfo) {
    return false;
}

@Override
public void endAnimation(RecyclerView.ViewHolder item) {}

@Override
public boolean animateChange(@NonNull RecyclerView.ViewHolder oldHolder, @NonNull RecyclerView.ViewHolder newHolder, @NonNull ItemHolderInfo preLayoutInfo, @NonNull ItemHolderInfo postLayoutInfo) {
    return false;
}

@Override
public void runPendingAnimations() {}

@Override
public boolean animateAppearance(@NonNull RecyclerView.ViewHolder viewHolder, @Nullable ItemHolderInfo preLayoutInfo, @NonNull ItemHolderInfo postLayoutInfo) {
    return false;
}

@Override
public boolean animateDisappearance(@NonNull RecyclerView.ViewHolder viewHolder, @NonNull ItemHolderInfo preLayoutInfo, @Nullable ItemHolderInfo postLayoutInfo) {
    return false;
}}

Now you can try:

TransitionManager.beginDelayedTransition(recyclerView);
recyclerViewAdapter.notifyItem... //add, remove, change etc.
Attainture answered 31/8, 2018 at 10:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.