5

tl;dr How to wait until the true scrolling is done after calling scrollToPosition()? What I mean by true scrolling is that (1) the RecyclerView has finished the scrolling and (2) it has bound all the ViewHolders for the set position of scroll.

Description:

I am trying to fix some transition animation for recycler view and I'm having a hard time achieving it.

The app is consistent of a RecyclerView in one of the activities and a ViewPager that acts as a "detail view" when users click on an item in the RecyclerView.

The forward navigation from RecyclerView to ViewPager works perfectly fine but the problem is, the backward navigation doesn't work. Please note that the user may navigate using the ViewPager in the detail view and when they re-enter the activity with RecyclerView, the position of the item may be different from the original case, meaning the RecyclerView needs to scoll first to the item and then resume the transition animation.

The reason I can't make it to work is because I resume the animation before the RecyclerView has properly scolled and bound the underlying ViewHolders but I don't know how to wait for the scrolling to truly finish and then resume the shared element transitions.

What I do in my code (on the Reenter code) is this:

if (isReentering) {
        // postpone the animation here
        ActivityCompat.postponeEnterTransition(getActivity());
        scollIndex = ... // determine the correct item position
        layoutManager.scrollToPosition(scrollIndex);

        final RecyclerView recyclerView = getRecyclerView();
        new Handler().post(new Runnable() {
            @Override
            public void run() {
                recyclerView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
                    @Override
                    public boolean onPreDraw() {
                        recyclerView.getViewTreeObserver().removeOnPreDrawListener(this);
                        recyclerView.requestLayout();
                        ActivityCompat.startPostponedEnterTransition(getActivity());
                        return true;
                    }
                });
            }
        });
    }

I also set the transition name in my Adapter as such:

@Override
public void onBindViewHolder(TViewHolder holder, int position) {
    ....
    holder.setTransitionName(_data.get(position).getContentId().toString());
}

The transition name is the UUID of the item, set in the underlying View. Both the ViewPager and the RecyclerView set this correctly.

The scrollIndex is correct and the RecyclerView does scroll to it but here's the catch: The scrolling and binding only takes effect after I've already started the postponed enter transition in my code (by calling ActivityCompat.startPostponedEnterTransition(getActivity());) which causes weird transition animations.

What I would like to happen is to somehow wait until the scrolling and the ViewHolder binding is finished before calling startPostponedEnterTransition so my question is, how can I find out when the scrolling has finished and all the ViewHolders are bound so that I can call this?

Many thanks in advance,

kha
  • 19,123
  • 9
  • 34
  • 67

1 Answers1

-1

You can check, if the ViewHolders have been bound, by using the code in this answer.

Community
  • 1
  • 1
Kilian Obermeier
  • 6,678
  • 4
  • 38
  • 50