Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Shared Element Transition with RecyclerView items - Android

I'm trying to make shared element transition work with an element inside a recycler view. When the user clicks on a textview inside my recycler view item, the Detail Activity opens. Inside Detail Activity, I display some infos and I also have a tab layout that loads some images from url using picasso. The transition to Detail Activity is working, but if the user returns to Main Activity before have loaded all images, the recycler view in Main Activity dissapers after the reverse animation! When I disable shared element transition, the problem is gone.

Both activities work with fragments. So, I'm trying to create a transition between two fragments, which are in different activities.

In RecyclerViewAdapter, I set the transition name:

public void onBindViewHolder(final ViewHolder viewHolder, int position) {
  ... 
 viewHolder.profileImage.setTransitionName("profile"+position);

onClickListener of my textview (inside a fragment in Main Activity):

Intent i = new Intent(getCurrentActivity(), DetailActivity.class);
        ActivityOptionsCompat options = ActivityOptionsCompat.
               makeSceneTransitionAnimation(getCurrentActivity(), (View) profileImage, "profile"+position);
        getCurrentActivity().startActivity(i, options.toBundle());

Inside the fragment of Detail Activity that has the shared element (in onCreateView):

profileImage.setTransitionName("profile"+position);

I already checked the transition name in both activities when the intent occurs and its the same.

I'm stuck in this problem for two days and can't see what is happening. If you need more info or code about it, just ask.

Thank you!

like image 770
G_comp Avatar asked Feb 08 '23 12:02

G_comp


1 Answers

The problem is that shared element transitions is started by the framework very early in the Activity lifecycle.Transitions must capture both the start and end state of its target views in order to build a properly functioning animation. Thus, if the framework starts the shared element transition before its shared elements are given their final size and position and size within the called Activity, the transition will capture the incorrect end values for its shared elements and the resulting animation will fail completely.

If The shared element depends on asynchronously loaded data by an AsyncTask, an AsyncQueryHandler, a Loader, or something similar before their final appearance within the called activity can be determined, the framework might start the transition before that data is delivered back to the main thread.
So,the soluation is the following:

  1. call postponeEnterTransition() in your called activity’s onCreate()method.
  2. when you know for certain that all of your shared elements have been properly positioned and sized, call startPostponedEnterTransition() to resume the transition. A common pattern you’ll find useful is to start the postponed transition in an OnPreDrawListener, which will be called after the shared element has been measured and laid out.

You use Picasso , as I know Picasso has a callback named RequestCreator when loaded image.
For example:

private final Callback callBack = new Callback() {
    @Override
    public void onSuccess() {
        imageView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
            @Override
            public boolean onPreDraw() {
                imageView.getViewTreeObserver().removeOnPreDrawListener(this);
                MainActivity.this.startPostponedEnterTransition();
                return true;
            }
        });
    }

    @Override
    public void onError() {

    }
};

RequestCreator requestCreator = Picasso.with(this).load(imageUrl);
requestCreator.into(imageView, callback);
like image 89
zys Avatar answered Feb 15 '23 10:02

zys