Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ViewPager Fragments – Shared Element Transitions

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 every image in the grid. This is done by passing a lists of paths (containing every image in the grid), along with an offset of the image that was tapped so the ViewPager can be set to show that page initially.

What's the best way to have a shared element transition inside the Fragment of the current offset page in the ViewPager? The grid (RecyclerView) image should expand into the full screen image in the current page. I saw the ability to postpone and resume activity transitions, so the app would wait to display the shared element transition until the image is loaded from the disk. But I want to be able to make it animate to the correct page in the view pager, and also exit to whatever the current page is when the user goes back (since you can swipe between pages). If you swipe to a different page now, the initial page is what animates back into the grid.

Currently, I assign every image in the Fragments of the view pager with a transitionName in the format "image_[index]". When I start the details activity, I use the same transitionName with the index being the offset.

Related to this, I was also wondering how to make ripples work with long presses. When you change a view's activated state, it seems to cancel the ripple. I want an effect similar to Gmail, where the ripple starts over again and quickly finishes after a long press is complete and triggers the activated state.

like image 935
afollestad Avatar asked Dec 04 '14 21:12

afollestad


People also ask

What is shared element transition?

Shared Element Transition is one of the most seen animations in Android apps. This type of animation is used when we have to open an item from a ListView or RecyclerView. Shared Element Transition in Android determines how shared element views are animated from activity to activity or fragment to fragment.

What is Fragment transition?

The Fragment API provides two ways to use motion effects and transformations to visually connect fragments during navigation. One of these is the Animation Framework, which uses both Animation and Animator . The other is the Transition Framework, which includes shared element transitions.

What is shared elements?

Shared Elements means certain elements of the project which are for the joint and mutual use and benefit of only certain Owners as set out in Section 6.1.

How do you animate a fragment?

To animate the transition between fragments, or to animate the process of showing or hiding a fragment you use the Fragment Manager to create a Fragment Transaction . Within each Fragment Transaction you can specify in and out animations that will be used for show and hide respectively (or both when replace is used).


1 Answers

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).

like image 68
Alex Lockwood Avatar answered Sep 29 '22 16:09

Alex Lockwood