An app I\'m developing displays a grid of images. When you tap an image, it goes into the details view. The details view contains a ViewPager that allows you swipe between e
From what I can tell (and correct me if I'm wrong), what you are trying to achieve is basically something like this: Assume you have a MainActivity
, a DetailsActivity
, and an arbitrary set of images. The MainActivity
displays the set of images in a grid and the DetailsActivity
displays the same set of images in a horizontal ViewPager
. When the user selects an image in the MainActivity
, that image should transition from its position in the grid to the correct page in the second activity's ViewPager
.
The problem we want to solve is "what if the user switches pages inside the DetailsActivity
"? If this happens, we want to change the shared image that will be used during the return transition. By default, the activity transition framework will use the shared element that was used during the enter transition... but the view pager's page has changed so obviously we want to somehow override this behavior. To do so, we will need to set a SharedElementCallback
in your MainActivity
and DetailsActivity
's onCreate()
methods and override the onMapSharedElements()
method like so:
private final SharedElementCallback mCallback = new SharedElementCallback() {
@Override
public void onMapSharedElements(List<String> names, Map<String, View> sharedElements) {
if (mCurrentImagePosition != mOriginalImagePosition) {
View sharedView = getImageAtPosition(mCurrentImagePosition);
names.clear();
sharedElements.clear();
names.add(sharedView.getTransitionName());
sharedElements.put(sharedView.getTransitionName(), sharedView);
}
}
/**
* Returns the image of interest to be used as the entering/returning
* shared element during the activity transition.
*/
private View getImageAtPosition(int position) {
// ...
}
};
For a more complete solution, I have created a sample project on GitHub that will achieve this effect (there is too much code to post in a single StackOverflow answer).
I'm assuming that you're using Fragment Transitions and that you're not animating between Activities. It is possible in both Activity Transitions and Fragment Transitions, but the specific code is a little different. The postpone is not available on Fragment Transitions, though.
The addSharedElement takes a second parameter. If you know the specific name in the target fragment when you call it, you can just choose the name in the details fragment to use. If you don't, you can choose any name you want and remap it with the SharedElementCallback set on the Fragment.
fragment.setEnterSharedElementCallback(new SharedElementCallback() {
@Override
public void onMapSharedElements(List<String> names, Map<String, View> sharedElements) {
sharedElements.put("detailView", mTargetDetailView);
}
});
If it doesn't match on the way back, the same call is made to remap it. This is likely going to be both in the calling fragment and the called fragment -- on the calling fragment, you use setExitSharedElementCallback. I expect this is the case in your app.
Likewise, in Activity Transitions, you set the same SharedElementCallback and use the same mapping, but you do it on the Activity instead.