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

Dfd02975cecba29510f6f8464e5bc916?s=128

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. Outlines Evolution of Mobile Apps UX Complexities Meaningful Animations Activity

    Transitions Conclusion
  4. A STORY!

  5. I’m an engineer/developer/programmer

  6. None
  7. None
  8. None
  9. Complicated environment Demands better apps

  10. Engineer UX/Design

  11. The Evolution of Mobile Apps At the beginning of all

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

    more possibilities But bad design strategies decrease UX quality
  13. The UX/UI Dilema Unnecessary Buttons Lack of context Bad use

    of design strategies
  14. 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.
  15. Motion Design

  16. Motion Design Where things come from, where do they go,

    what can I do. Motion Matters
  17. Motion Design Where things come from GOOD BAD

  18. Motion Design Where do they go

  19. Motion Design What can I do

  20. 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
  21. Motion Design Animations to the rescue Animations can help simplify

    your app and eliminate unnecessary tutorials or even buttons
  22. Motion Design Just answer these 3 questions Where things come

    from Where do they go What can I do
  23. Motion Design Your animations should make sense It should have

    a reason to exist
  24. None
  25. Activity Transitions

  26. Activity Transitions Activity transitions in material design apps provide visual

    connections between different states through motion and transformations between common elements
  27. 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
  28. Default Activity Transition

  29. Cool Activity Transition :)

  30. Even Cooler Activity Transition :)

  31. Provided Activity Transition Animations - Explode getWindow().setEnterTransition(new Explode()); getWindow().setExitTransition(new Explode());

  32. - Slide getWindow().setEnterTransition(new Slide(Gravity.TOP)); getWindow().setExitTransition(new Slide(Gravity.Bottom)); Provided Activity Transition Animations

  33. 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
  34. Cool Activity Transition :)

  35. 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
  36. 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
  37. 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
  38. @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
  39. @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
  40. Result

  41. public void makeEnterTransition(){
 getWindow().setEnterTransition(new Slide(Gravity.TOP));
 } Add enter transition MovieDetailActivity.java

  42. Result

  43. Cool Activity Transition :)

  44. public void makeEnterTransition(){
 getWindow().setEnterTransition(new Slide(Gravity.TOP));
 } Add enter transition MovieDetailActivity.java

  45. 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
  46. 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
  47. 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
  48. 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
  49. Result

  50. Result

  51. 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
  52. Result

  53. Result WHY U DON’T WORK!

  54. Activity Transitions are easy they said It will save you

    time they said
  55. 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.
  56. 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.
  57. 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.
  58. 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.
  59. The Catch The framework considers views with background as transitionGroup

  60. 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" />
  61. The Fix

  62. The Fix …
 cardInfo.setTransitionGroup(false);
 makeEnterTransition();

  63. Result

  64. 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
  65. 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
  66. 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
  67. 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
  68. Add Exit and Return transition @Override
 public void onBackPressed() {


    makeExitTransition();
 super.onBackPressed();
 } MovieDetailActivity.java
  69. Result

  70. Still not perfect

  71. 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
  72. 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
  73. 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
  74. 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
  75. 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
  76. Result

  77. Bonus

  78. Bonus

  79. 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);
 }
 });
  80. 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);
 }
 });
  81. 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);
 }
 });
  82. 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);
 }
 });
  83. 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);
 }
 });
  84. Bonus

  85. Activity Transitions - Easy to use once understand how it

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

    layout will directly affect how your Activity Transition Animations will work.
  87. https://github.com/marcospaulo/cinema_example Thank You Marcos Damasceno @marcospaulosd