Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Animation To Guide Us All 2nd Edition

Animation To Guide Us All 2nd Edition

At DevFest Seattle and Android TO I talked about how animations can greatly increase the UX of your app and make it more simple.

The source code for the project can be found here: https://github.com/marcospaulo/cinema_example

Marcos Paulo Souza Damasceno

October 15, 2016
Tweet

More Decks by Marcos Paulo Souza Damasceno

Other Decks in Technology

Transcript

  1. Animations to Guide Us All How animations can help guide

    your users +Marcos Damasceno @marcospaulosd
  2. +Marcos Damasceno @marcospaulosd Google Developer Expert Android Android Engineer @

    Mirego Droidcon Montreal and GDG Android Montreal Organizer Speaker (Droidcon NYC, London…) Brazilian
  3. The Evolution of Mobile Apps At the beginning of all

    times, Mobile Applications were there for simple uses.
  4. The Evolution of Mobile Apps Big screens have brought way

    more possibilities But bad design strategies decrease UX quality
  5. The UX/UI Dilema Coding an app is not the hardest

    part anymore, but actually knowing where to put your elements, functionalities and even how to do the flow of your app is the real challenge.
  6. Drawables Overview We will see how we can take advantage

    of drawables so we can reduce the amount of resources in our application. Also we will see cases where a drawable could easily replace views, making our app more clean and faster. Objective
  7. Motion Design Animations to the rescue Animations can help simplify

    your app and eliminate unnecessary tutorials or even buttons
  8. Activity Transitions Activity transitions in material design apps provide visual

    connections between different states through motion and transformations between common elements
  9. Activity Transitions Enter Exit Shared Element How views in an

    activity enter the scene How views in an activity exit the scene How views shared between 2 activities transition
  10. Animations should make sense Choreography should be used to show

    the elements of your screen to the user, guiding him so he can know what he can do
  11. rvMovies.setAdapter(new MoviesAdapter(Movie.createMovies(), new MoviesAdapter.OnMovieClickListener() {
 @Override
 public void onMovieClick(Movie movie,

    ImageView ivMovieCover) {
 Intent intent = MovieDetailActivity.newIntent(MainActivity.this, movie);
 ivMovieCover.setTransitionName("movie_cover");
 startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(MainActivity.this, ivMovieCover, "movie_cover").toBundle());
 }
 })); We need access to the element that will be shared MoviesActivity.java
  12. rvMovies.setAdapter(new MoviesAdapter(Movie.createMovies(), new MoviesAdapter.OnMovieClickListener() {
 @Override
 public void onMovieClick(Movie movie,

    ImageView ivMovieCover) {
 Intent intent = MovieDetailActivity.newIntent(MainActivity.this, movie);
 ivMovieCover.setTransitionName("movie_cover");
 startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(MainActivity.this, ivMovieCover, "movie_cover").toBundle());
 }
 })); Set Transition Name MoviesActivity.java
  13. rvMovies.setAdapter(new MoviesAdapter(Movie.createMovies(), new MoviesAdapter.OnMovieClickListener() {
 @Override
 public void onMovieClick(Movie movie,

    ImageView ivMovieCover) {
 Intent intent = MovieDetailActivity.newIntent(MainActivity.this, movie);
 ivMovieCover.setTransitionName("movie_cover");
 startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(MainActivity.this, ivMovieCover, "movie_cover").toBundle());
 }
 })); Pass view and transition name MoviesActivity.java
  14. @Override
 public void onCreate(Bundle savedInstanceState) {
 getWindow().getDecorView().setSystemUiVisibility(
 View.SYSTEM_UI_FLAG_LAYOUT_STABLE
 | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);


    super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_movie_detail);
 ButterKnife.bind(this);
 
 movie = (Movie) getIntent().getSerializableExtra(EXTRA_MOVIE);
 
 toolbar.setBackgroundResource(movie.resImageBanner);
 ivMovieCover.setImageResource(movie.resImageCover);
 tvMovieTitle.setText(movie.name);
 tvMovieSubtitle.setText(movie.subtitle);
 tvMovieDescription.setText(movie.description);
 
 ivMovieCover.setTransitionName("movie_cover");
 } Set transition name in the next activity MovieDetailActivity.java
  15. @Override
 public void onCreate(Bundle savedInstanceState) {
 getWindow().getDecorView().setSystemUiVisibility(
 View.SYSTEM_UI_FLAG_LAYOUT_STABLE
 | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);


    super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_movie_detail);
 ButterKnife.bind(this);
 
 movie = (Movie) getIntent().getSerializableExtra(EXTRA_MOVIE);
 
 toolbar.setBackgroundResource(movie.resImageBanner);
 ivMovieCover.setImageResource(movie.resImageCover);
 tvMovieTitle.setText(movie.name);
 tvMovieSubtitle.setText(movie.subtitle);
 tvMovieDescription.setText(movie.description);
 
 ivMovieCover.setTransitionName("movie_cover");
 } Set transition name in the next activity MovieDetailActivity.java
  16. public void makeEnterTransition(){
 Slide slideFromUp = new Slide(Gravity.TOP);
 slideFromUp.addTarget(R.id.toolbar);
 


    Slide slideFromBottom = new Slide(Gravity.BOTTOM);
 slideFromBottom.addTarget(R.id.tv_movie_description);
 slideFromBottom.addTarget(R.id.tv_movie_subtitle);
 slideFromBottom.addTarget(R.id.tv_movie_title);
 
 TransitionSet transitionSet = new TransitionSet();
 transitionSet.addTransition(slideFromUp);
 transitionSet.addTransition(slideFromBottom);
 transitionSet.setOrdering(TransitionSet.ORDERING_SEQUENTIAL);
 
 
 getWindow().setEnterTransition(transitionSet);
 } Defining different transitions MovieDetailActivity.java
  17. public void makeEnterTransition(){
 Slide slideFromUp = new Slide(Gravity.TOP);
 slideFromUp.addTarget(R.id.toolbar);
 


    Slide slideFromBottom = new Slide(Gravity.BOTTOM);
 slideFromBottom.addTarget(R.id.tv_movie_description);
 slideFromBottom.addTarget(R.id.tv_movie_subtitle);
 slideFromBottom.addTarget(R.id.tv_movie_title);
 
 TransitionSet transitionSet = new TransitionSet();
 transitionSet.addTransition(slideFromUp);
 transitionSet.addTransition(slideFromBottom);
 transitionSet.setOrdering(TransitionSet.ORDERING_SEQUENTIAL);
 
 
 getWindow().setEnterTransition(transitionSet);
 } Defining different transitions MovieDetailActivity.java
  18. public void makeEnterTransition(){
 Slide slideFromUp = new Slide(Gravity.TOP);
 slideFromUp.addTarget(R.id.toolbar);
 


    Slide slideFromBottom = new Slide(Gravity.BOTTOM);
 slideFromBottom.addTarget(R.id.tv_movie_description);
 slideFromBottom.addTarget(R.id.tv_movie_subtitle);
 slideFromBottom.addTarget(R.id.tv_movie_title);
 
 TransitionSet transitionSet = new TransitionSet();
 transitionSet.addTransition(slideFromUp);
 transitionSet.addTransition(slideFromBottom);
 transitionSet.setOrdering(TransitionSet.ORDERING_SEQUENTIAL);
 
 
 getWindow().setEnterTransition(transitionSet);
 } Defining different transitions MovieDetailActivity.java
  19. public void makeEnterTransition(){
 Slide slideFromUp = new Slide(Gravity.TOP);
 slideFromUp.addTarget(R.id.toolbar);
 


    Slide slideFromBottom = new Slide(Gravity.BOTTOM);
 slideFromBottom.addTarget(R.id.tv_movie_description);
 slideFromBottom.addTarget(R.id.tv_movie_subtitle);
 slideFromBottom.addTarget(R.id.tv_movie_title);
 
 TransitionSet transitionSet = new TransitionSet();
 transitionSet.addTransition(slideFromUp);
 transitionSet.addTransition(slideFromBottom);
 transitionSet.setOrdering(TransitionSet.ORDERING_SEQUENTIAL);
 
 
 getWindow().setEnterTransition(transitionSet);
 } Defining different transitions MovieDetailActivity.java
  20. public void makeEnterTransition(){
 Slide slideFromUp = new Slide(Gravity.TOP);
 slideFromUp.addTarget(R.id.toolbar);
 


    Slide slideFromBottom = new Slide(Gravity.BOTTOM);
 slideFromBottom.addTarget(R.id.tv_movie_description);
 slideFromBottom.addTarget(R.id.tv_movie_subtitle);
 slideFromBottom.addTarget(R.id.tv_movie_title);
 
 TransitionSet transitionSet = new TransitionSet();
 transitionSet.addTransition(slideFromUp);
 transitionSet.addTransition(slideFromBottom);
 transitionSet.setOrdering(TransitionSet.ORDERING_SEQUENTIAL);
 
 
 getWindow().setEnterTransition(transitionSet);
 } Defining different transitions MovieDetailActivity.java
  21. The problem /** @hide */
 @Override
 public void captureTransitioningViews(List<View> transitioningViews)

    {
 if (getVisibility() != View.VISIBLE) {
 return;
 }
 if (isTransitionGroup()) {
 transitioningViews.add(this);
 } else {
 int count = getChildCount();
 for (int i = 0; i < count; i++) {
 View child = getChildAt(i);
 child.captureTransitioningViews(transitioningViews);
 }
 }
 } Before the transition starts, the framework constructs the set of transitioning views by performing a recursive search on the Activity window’s (or Fragment’s) entire view hierarchy.
  22. The problem /** @hide */
 @Override
 public void captureTransitioningViews(List<View> transitioningViews)

    {
 if (getVisibility() != View.VISIBLE) {
 return;
 }
 if (isTransitionGroup()) {
 transitioningViews.add(this);
 } else {
 int count = getChildCount();
 for (int i = 0; i < count; i++) {
 View child = getChildAt(i);
 child.captureTransitioningViews(transitioningViews);
 }
 }
 } Before the transition starts, the framework constructs the set of transitioning views by performing a recursive search on the Activity window’s (or Fragment’s) entire view hierarchy.
  23. The problem /** @hide */
 @Override
 public void captureTransitioningViews(List<View> transitioningViews)

    {
 if (getVisibility() != View.VISIBLE) {
 return;
 }
 if (isTransitionGroup()) {
 transitioningViews.add(this);
 } else {
 int count = getChildCount();
 for (int i = 0; i < count; i++) {
 View child = getChildAt(i);
 child.captureTransitioningViews(transitioningViews);
 }
 }
 } Before the transition starts, the framework constructs the set of transitioning views by performing a recursive search on the Activity window’s (or Fragment’s) entire view hierarchy.
  24. The problem /** @hide */
 @Override
 public void captureTransitioningViews(List<View> transitioningViews)

    {
 if (getVisibility() != View.VISIBLE) {
 return;
 }
 if (isTransitionGroup()) {
 transitioningViews.add(this);
 } else {
 int count = getChildCount();
 for (int i = 0; i < count; i++) {
 View child = getChildAt(i);
 child.captureTransitioningViews(transitioningViews);
 }
 }
 } Before the transition starts, the framework constructs the set of transitioning views by performing a recursive search on the Activity window’s (or Fragment’s) entire view hierarchy.
  25. The problem <android.support.v7.widget.CardView
 android:id="@+id/card_info"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:layout_below="@+id/toolbar"
 android:elevation="0dp"
 app:cardElevation="8dp">
 


    <LinearLayout
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:orientation="vertical">
 
 <LinearLayout
 android:layout_width="match_parent"
 android:layout_height="128dp"
 android:paddingLeft="128dp"
 android:orientation="vertical">
 
 <TextView
 android:id="@+id/tv_movie_title"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:layout_marginBottom="8dp"
 android:layout_marginTop="8dp"
 tools:text="Batman v Superman: Dawn of Justice"
 android:textColor="@android:color/black"
 android:textSize="20dp" />
 
 <TextView
 android:id="@+id/tv_movie_subtitle"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 tools:text="June 2013 PG 142 minutes" />
  26. Add Exit and Return transition private void makeExitTransition(){
 cardInfo.setTransitionGroup(true);
 


    Slide slideFromUp = new Slide(Gravity.TOP);
 slideFromUp.addTarget(R.id.toolbar);
 
 Slide slideFromBottom = new Slide(Gravity.BOTTOM);
 slideFromBottom.addTarget(R.id.card_info);
 
 TransitionSet transitionSet = new TransitionSet();
 transitionSet.addTransition(slideFromBottom);
 transitionSet.addTransition(slideFromUp);
 
 getWindow().setExitTransition(transitionSet);
 getWindow().setReturnTransition(transitionSet);
 } MovieDetailActivity.java
  27. Add Exit and Return transition private void makeExitTransition(){
 cardInfo.setTransitionGroup(true);
 


    Slide slideFromUp = new Slide(Gravity.TOP);
 slideFromUp.addTarget(R.id.toolbar);
 
 Slide slideFromBottom = new Slide(Gravity.BOTTOM);
 slideFromBottom.addTarget(R.id.card_info);
 
 TransitionSet transitionSet = new TransitionSet();
 transitionSet.addTransition(slideFromBottom);
 transitionSet.addTransition(slideFromUp);
 
 getWindow().setExitTransition(transitionSet);
 getWindow().setReturnTransition(transitionSet);
 } MovieDetailActivity.java
  28. Add Exit and Return transition private void makeExitTransition(){
 cardInfo.setTransitionGroup(true);
 


    Slide slideFromUp = new Slide(Gravity.TOP);
 slideFromUp.addTarget(R.id.toolbar);
 
 Slide slideFromBottom = new Slide(Gravity.BOTTOM);
 slideFromBottom.addTarget(R.id.card_info);
 
 TransitionSet transitionSet = new TransitionSet();
 transitionSet.addTransition(slideFromBottom);
 transitionSet.addTransition(slideFromUp);
 
 getWindow().setExitTransition(transitionSet);
 getWindow().setReturnTransition(transitionSet);
 } MovieDetailActivity.java
  29. Add Exit and Return transition private void makeExitTransition(){
 cardInfo.setTransitionGroup(true);
 


    Slide slideFromUp = new Slide(Gravity.TOP);
 slideFromUp.addTarget(R.id.toolbar);
 
 Slide slideFromBottom = new Slide(Gravity.BOTTOM);
 slideFromBottom.addTarget(R.id.card_info);
 
 TransitionSet transitionSet = new TransitionSet();
 transitionSet.addTransition(slideFromBottom);
 transitionSet.addTransition(slideFromUp);
 
 getWindow().setExitTransition(transitionSet);
 getWindow().setReturnTransition(transitionSet);
 } MovieDetailActivity.java
  30. Add Exit and Return transition @Override
 public void onBackPressed() {


    makeExitTransition();
 super.onBackPressed();
 } MovieDetailActivity.java
  31. public void makeEnterTransition(){
 Slide slideFromUp = new Slide(Gravity.TOP);
 slideFromUp.addTarget(R.id.toolbar);
 


    Slide slideFromBottom = new Slide(Gravity.BOTTOM);
 slideFromBottom.addTarget(R.id.tv_movie_description);
 slideFromBottom.addTarget(R.id.tv_movie_subtitle);
 slideFromBottom.addTarget(R.id.tv_movie_title);
 
 TransitionSet transitionSet = new TransitionSet();
 transitionSet.addTransition(slideFromUp);
 transitionSet.addTransition(slideFromBottom);
 transitionSet.setOrdering(TransitionSet.ORDERING_SEQUENTIAL);
 
 
 getWindow().setEnterTransition(transitionSet);
 } Defining different transitions MovieDetailActivity.java
  32. Let’s make it better private void makeEnterTransition() {
 Slide slideFromUp

    = new Slide(Gravity.TOP);
 slideFromUp.addTarget(R.id.toolbar);
 
 Slide slideFromBottom = new Slide(Gravity.BOTTOM);
 slideFromBottom.setDuration(500);
 slideFromBottom.addTarget(R.id.tv_movie_description);
 slideFromBottom.addTarget(R.id.tv_movie_subtitle);
 slideFromBottom.addTarget(R.id.tv_movie_title);
 
 Fade fade = new Fade();
 fade.setDuration(1000);
 fade.addTarget(R.id.tv_movie_description);
 fade.addTarget(R.id.tv_movie_subtitle);
 fade.addTarget(R.id.tv_movie_title);
 
 TransitionSet transitionSetInfo = new TransitionSet();
 transitionSetInfo.addTransition(slideFromBottom);
 transitionSetInfo.addTransition(fade);
 
 
 TransitionSet transitionSet = new TransitionSet();
 transitionSet.addTransition(slideFromUp);
 transitionSet.addTransition(transitionSetInfo);
 transitionSet.setOrdering(TransitionSet.ORDERING_SEQUENTIAL);
 
 getWindow().setEnterTransition(transitionSet);
 } MovieDetailActivity.java
  33. private void makeEnterTransition() {
 Slide slideFromUp = new Slide(Gravity.TOP);
 slideFromUp.addTarget(R.id.toolbar);


    
 Slide slideFromBottom = new Slide(Gravity.BOTTOM);
 slideFromBottom.setDuration(500);
 slideFromBottom.addTarget(R.id.tv_movie_description);
 slideFromBottom.addTarget(R.id.tv_movie_subtitle);
 slideFromBottom.addTarget(R.id.tv_movie_title);
 
 Fade fade = new Fade();
 fade.setDuration(1000);
 fade.addTarget(R.id.tv_movie_description);
 fade.addTarget(R.id.tv_movie_subtitle);
 fade.addTarget(R.id.tv_movie_title);
 
 TransitionSet transitionSetInfo = new TransitionSet();
 transitionSetInfo.addTransition(slideFromBottom);
 transitionSetInfo.addTransition(fade);
 
 
 TransitionSet transitionSet = new TransitionSet();
 transitionSet.addTransition(slideFromUp);
 transitionSet.addTransition(transitionSetInfo);
 transitionSet.setOrdering(TransitionSet.ORDERING_SEQUENTIAL);
 
 getWindow().setEnterTransition(transitionSet);
 } Let’s make it better MovieDetailActivity.java
  34. private void makeEnterTransition() {
 Slide slideFromUp = new Slide(Gravity.TOP);
 slideFromUp.addTarget(R.id.toolbar);


    
 Slide slideFromBottom = new Slide(Gravity.BOTTOM);
 slideFromBottom.setDuration(500);
 slideFromBottom.addTarget(R.id.tv_movie_description);
 slideFromBottom.addTarget(R.id.tv_movie_subtitle);
 slideFromBottom.addTarget(R.id.tv_movie_title);
 
 Fade fade = new Fade();
 fade.setDuration(1000);
 fade.addTarget(R.id.tv_movie_description);
 fade.addTarget(R.id.tv_movie_subtitle);
 fade.addTarget(R.id.tv_movie_title);
 
 TransitionSet transitionSetInfo = new TransitionSet();
 transitionSetInfo.addTransition(slideFromBottom);
 transitionSetInfo.addTransition(fade);
 
 
 TransitionSet transitionSet = new TransitionSet();
 transitionSet.addTransition(slideFromUp);
 transitionSet.addTransition(transitionSetInfo);
 transitionSet.setOrdering(TransitionSet.ORDERING_SEQUENTIAL);
 
 getWindow().setEnterTransition(transitionSet);
 } MovieDetailActivity.java Let’s make it better
  35. private void makeEnterTransition() {
 Slide slideFromUp = new Slide(Gravity.TOP);
 slideFromUp.addTarget(R.id.toolbar);


    
 Slide slideFromBottom = new Slide(Gravity.BOTTOM);
 slideFromBottom.setDuration(500);
 slideFromBottom.addTarget(R.id.tv_movie_description);
 slideFromBottom.addTarget(R.id.tv_movie_subtitle);
 slideFromBottom.addTarget(R.id.tv_movie_title);
 
 Fade fade = new Fade();
 fade.setDuration(1000);
 fade.addTarget(R.id.tv_movie_description);
 fade.addTarget(R.id.tv_movie_subtitle);
 fade.addTarget(R.id.tv_movie_title);
 
 TransitionSet transitionSetInfo = new TransitionSet();
 transitionSetInfo.addTransition(slideFromBottom);
 transitionSetInfo.addTransition(fade);
 
 
 TransitionSet transitionSet = new TransitionSet();
 transitionSet.addTransition(slideFromUp);
 transitionSet.addTransition(transitionSetInfo);
 transitionSet.setOrdering(TransitionSet.ORDERING_SEQUENTIAL);
 
 getWindow().setEnterTransition(transitionSet);
 } Let’s make it better MovieDetailActivity.java
  36. Add reveal for movie banner MovieDetailActivity.java toolbar.setVisibility(View.INVISIBLE);
 setEnterSharedElementCallback(new SharedElementCallback() {


    @Override
 public void onSharedElementEnd(List<String> sharedElementNames, List<View> sharedElements, List<View> sharedElementSnapshots) {
 final Animator animator = ViewAnimationUtils.createCircularReveal(toolbar, cardInfo.getRight() / 2, cardInfo.getTop() / 2, 0, cardInfo.getWidth() + cardInfo.getHeight());
 Handler handler = new Handler();
 animator.setInterpolator(new AccelerateDecelerateInterpolator());
 animator.setDuration(600);
 handler.postDelayed(new Runnable() {
 @Override
 public void run() {
 toolbar.setVisibility(View.VISIBLE);
 animator.start();
 }
 }, 300);
 }
 });
  37. Add reveal for movie banner MovieDetailActivity.java toolbar.setVisibility(View.INVISIBLE);
 setEnterSharedElementCallback(new SharedElementCallback() {


    @Override
 public void onSharedElementEnd(List<String> sharedElementNames, List<View> sharedElements, List<View> sharedElementSnapshots) {
 final Animator animator = ViewAnimationUtils.createCircularReveal(toolbar, cardInfo.getRight() / 2, cardInfo.getTop() / 2, 0, cardInfo.getWidth() + cardInfo.getHeight());
 Handler handler = new Handler();
 animator.setInterpolator(new AccelerateDecelerateInterpolator());
 animator.setDuration(600);
 handler.postDelayed(new Runnable() {
 @Override
 public void run() {
 toolbar.setVisibility(View.VISIBLE);
 animator.start();
 }
 }, 300);
 }
 });
  38. Add reveal for movie banner MovieDetailActivity.java toolbar.setVisibility(View.INVISIBLE);
 setEnterSharedElementCallback(new SharedElementCallback() {


    @Override
 public void onSharedElementEnd(List<String> sharedElementNames, List<View> sharedElements, List<View> sharedElementSnapshots) {
 final Animator animator = ViewAnimationUtils.createCircularReveal(toolbar, cardInfo.getRight() / 2, cardInfo.getTop() / 2, 0, cardInfo.getWidth() + cardInfo.getHeight());
 Handler handler = new Handler();
 animator.setInterpolator(new AccelerateDecelerateInterpolator());
 animator.setDuration(600);
 handler.postDelayed(new Runnable() {
 @Override
 public void run() {
 toolbar.setVisibility(View.VISIBLE);
 animator.start();
 }
 }, 300);
 }
 });
  39. Add reveal for movie banner MovieDetailActivity.java toolbar.setVisibility(View.INVISIBLE);
 setEnterSharedElementCallback(new SharedElementCallback() {


    @Override
 public void onSharedElementEnd(List<String> sharedElementNames, List<View> sharedElements, List<View> sharedElementSnapshots) {
 final Animator animator = ViewAnimationUtils.createCircularReveal(toolbar, cardInfo.getRight() / 2, cardInfo.getTop() / 2, 0, cardInfo.getWidth() + cardInfo.getHeight());
 Handler handler = new Handler();
 animator.setInterpolator(new AccelerateDecelerateInterpolator());
 animator.setDuration(600);
 handler.postDelayed(new Runnable() {
 @Override
 public void run() {
 toolbar.setVisibility(View.VISIBLE);
 animator.start();
 }
 }, 300);
 }
 });
  40. Add reveal for movie banner MovieDetailActivity.java toolbar.setVisibility(View.INVISIBLE);
 setEnterSharedElementCallback(new SharedElementCallback() {


    @Override
 public void onSharedElementEnd(List<String> sharedElementNames, List<View> sharedElements, List<View> sharedElementSnapshots) {
 final Animator animator = ViewAnimationUtils.createCircularReveal(toolbar, cardInfo.getRight() / 2, cardInfo.getTop() / 2, 0, cardInfo.getWidth() + cardInfo.getHeight());
 Handler handler = new Handler();
 animator.setInterpolator(new AccelerateDecelerateInterpolator());
 animator.setDuration(600);
 handler.postDelayed(new Runnable() {
 @Override
 public void run() {
 toolbar.setVisibility(View.VISIBLE);
 animator.start();
 }
 }, 300);
 }
 });
  41. Activity Transitions - Easy to use once understand how it

    works - Limited customization due to TransitioGroup handling - Only available on Lollipop +
  42. THINK LIKE AN ANIMATOR The way you write your xml

    layout will directly affect how your Activity Transition Animations will work.