4

I have a RecyclerView with images and when I press an image the app opens another activity that contains a ViewPager with the same images but in the position of the one I selected.

I've done the transition in Lollipop to share this image between activities using supportPostponeEnterTransition and supportStartPostponedEnterTransition in the called activity to wait until the viewPager is loaded with images to start the transition.

When I enter in the called activity and when I press back the transitions are ok.

The problem I'm facing is if I move to another image in the ViewPager of the called activity, when I press back it animates the image that it was selected at the beginning, not the currently selected one.

I've been able to change the animated image to the one selected in the called activity with this:

@Override
public void onBackPressed() {
  View view = ((ImageDetailFragment) adapter.getFragment(viewPager,
      viewPager.getCurrentItem())).getTransitionView();

  ViewCompat.setTransitionName(view, Constants.TRANSITION_IMAGE);
  super.onBackPressed();
}

But it is returning to the same position of the original image in the list of the calling activity.

How can I do it to make the image return to its position in the list of the calling activity?

jekopena
  • 43
  • 6

1 Answers1

6

The first thing to do is to make sure that the views work properly without any Activity transition. That is, when your return from Activity with the ViewPager, the RecyclerView Activity should be showing the View that the ViewPage was showing. When you call the ViewPager activity, use startActivityForResult and use the result to scroll the RecyclerView to the correct position.

Once that is working, the Activity Transition can be made to work. I know that you've given each View in your RecyclerView a different transitionName, right? When you bind the View, call setTransitionName and give it a repeatable name. Typically this is the image URL or cursor row ID or at worst some munged index like "image_" + index.

The next thing you need to do is set the SharedElementCallback for both the calling Activity (exit) and called activity (enter). In each, you're going to need to override the onMapSharedElements callback to remap the shared element.

@Override
public void onMapSharedElements(List<String> names, Map<String, View> sharedElements) {
    // assuming just one shared element, excuse the ugly code
    sharedElements.put(names.get(0), mSharedElement);        
}

Here, mSharedElement has been set in the onActivityReenter in the calling (RecyclerView) activity and in onCreate and prior to finishAfterTransition (onBackPressed?) in the called (ViewPager) activity.

The onActivityReenter gives new functionality specifically for this case. You can look at the results there before the called Activity completes.

George Mount
  • 20,708
  • 2
  • 73
  • 61
  • This is very well explained and it's working great when the user has moved to a different image than the original one that is currently being shown in the RecyclerView. The problem I have now is when the user moves to an image in the ViewPager than is not being shown in the RecyclerView. I did the first step of scrolling to the new position in the onActivityResult. But this method is being called after onActivityReenter so when I try to get the sharedElement view with something like "rvImages.findViewHolderForPosition(position).itemView.findViewById(R.id.iv_photo);" I always receive a null. – jekopena Apr 12 '15 at 14:43
  • And it happens the same if I try to scroll in the same onActivityReenter method before getting the sharedElement view. As the view hasn't been inflated yet, I can't get it. Any solution to this? – jekopena Apr 12 '15 at 14:48
  • You can call postponeEnterTransition() in the onActivityReenter to ensure the view is ready before you start the transition. When it is ready, call startPostponedEnterTransition() – George Mount Apr 13 '15 at 17:11
  • Awesome, that did it. I had to get the sharedElement in a OnGlobalLayoutListener of the RecyclerView after scrolling and call startPostponedEnterTransition(). – jekopena Apr 14 '15 at 13:03
  • I am doing the same thing, but I am also sending a parcelable Object as one of the parameters other than the Current_position in finishAfterTransition(). The problem is when I try to access any of the intent data in onActivityReenter(), it throws an exception. I have posted it at http://stackoverflow.com/questions/31876767/intent-not-working-for-parcelable-objects-in-onactivityreenter-with-sharedelemen Can you please help me with this exception. – Roadblock Aug 10 '15 at 09:45
  • Also, I tried using the startActivityForResult, but when I do a PostponeEnterTransition in onActivityReenter and try to do startPostponedEnterTransition in onActivityResult, the animation just doesn't happen. The screen goes blank other than the SharedElement From ActivityB. – Roadblock Aug 10 '15 at 09:48
  • Also, I tried using the startActivityForResult, but when I do a PostponeEnterTransition in onActivityReenter and try to do startPostponedEnterTransition in onActivityResult, the animation just doesn't happen (onActivityResult never gets called). The screen goes blank other than the SharedElement From ActivityB. It never crashes. So, I think I might be stopping the execution somehow. I just dont know where. – Roadblock Aug 10 '15 at 09:53
  • Same thing for me. If I put PostponeEnterTransition in onResume it seems like the animation is not postponed. When I put it in onActivityReenter it freezez. Without PostponeEnterTransition it works but the animation is glitchy due to that the image is not loaded yet. Did you find a solution? – Rickard Lindroth May 31 '17 at 07:39