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

    View full-size slide

  2. +Marcos Damasceno
    @marcospaulosd
    Google Developer Expert Android
    Android Engineer @ Mirego
    Droidcon Montreal and
    GDG Android Montreal Organizer
    Speaker (Droidcon NYC, London…)
    Brazilian

    View full-size slide

  3. Outlines
    Evolution of Mobile Apps
    UX Complexities
    Meaningful Animations
    Activity Transitions
    Conclusion

    View full-size slide

  4. I’m an engineer/developer/programmer

    View full-size slide

  5. Complicated environment
    Demands better apps

    View full-size slide

  6. Engineer UX/Design

    View full-size slide

  7. The Evolution of Mobile Apps
    At the beginning of all times, Mobile Applications
    were there for simple uses.

    View full-size slide

  8. The Evolution of Mobile Apps
    Big screens have brought way more possibilities
    But bad design strategies decrease UX quality

    View full-size slide

  9. The UX/UI Dilema
    Unnecessary Buttons
    Lack of context
    Bad use of design strategies

    View full-size slide

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

    View full-size slide

  11. Motion Design

    View full-size slide

  12. Motion Design
    Where things come from,
    where do they go, what can I do.
    Motion Matters

    View full-size slide

  13. Motion Design
    Where things come from
    GOOD BAD

    View full-size slide

  14. Motion Design
    Where do they go

    View full-size slide

  15. Motion Design
    What can I do

    View full-size slide

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

    View full-size slide

  17. Motion Design
    Animations to the rescue
    Animations can help simplify your
    app and eliminate unnecessary
    tutorials or even buttons

    View full-size slide

  18. Motion Design
    Just answer these 3 questions
    Where things come from
    Where do they go
    What can I do

    View full-size slide

  19. Motion Design
    Your animations should make sense
    It should have a reason to exist

    View full-size slide

  20. Activity Transitions

    View full-size slide

  21. Activity Transitions
    Activity transitions in material design apps provide visual connections
    between different states through motion and transformations between
    common elements

    View full-size slide

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

    View full-size slide

  23. Default Activity Transition

    View full-size slide

  24. Cool Activity Transition :)

    View full-size slide

  25. Even Cooler Activity Transition :)

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  29. Cool Activity Transition :)

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  33. @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

    View full-size slide

  34. @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

    View full-size slide

  35. public void makeEnterTransition(){

    getWindow().setEnterTransition(new Slide(Gravity.TOP));

    }
    Add enter transition
    MovieDetailActivity.java

    View full-size slide

  36. Cool Activity Transition :)

    View full-size slide

  37. public void makeEnterTransition(){

    getWindow().setEnterTransition(new Slide(Gravity.TOP));

    }
    Add enter transition
    MovieDetailActivity.java

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  43. Result
    WHY U
    DON’T
    WORK!

    View full-size slide

  44. Activity Transitions are easy they said
    It will save you time they said

    View full-size slide

  45. The problem
    /** @hide */

    @Override

    public void captureTransitioningViews(List 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.

    View full-size slide

  46. The problem
    /** @hide */

    @Override

    public void captureTransitioningViews(List 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.

    View full-size slide

  47. The problem
    /** @hide */

    @Override

    public void captureTransitioningViews(List 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.

    View full-size slide

  48. The problem
    /** @hide */

    @Override

    public void captureTransitioningViews(List 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.

    View full-size slide

  49. The Catch
    The framework considers views with background as transitionGroup

    View full-size slide

  50. The problem 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">


    android:layout_width="match_parent"

    android:layout_height="wrap_content"

    android:orientation="vertical">


    android:layout_width="match_parent"

    android:layout_height="128dp"

    android:paddingLeft="128dp"

    android:orientation="vertical">


    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" />


    android:id="@+id/tv_movie_subtitle"

    android:layout_width="wrap_content"

    android:layout_height="wrap_content"

    tools:text="June 2013 PG 142 minutes" />

    View full-size slide

  51. The Fix
    …

    cardInfo.setTransitionGroup(false);

    makeEnterTransition();

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  56. Add Exit and Return transition
    @Override

    public void onBackPressed() {

    makeExitTransition();

    super.onBackPressed();

    }
    MovieDetailActivity.java

    View full-size slide

  57. Still not perfect

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  63. Add reveal for movie banner
    MovieDetailActivity.java
    toolbar.setVisibility(View.INVISIBLE);

    setEnterSharedElementCallback(new SharedElementCallback() {

    @Override

    public void onSharedElementEnd(List sharedElementNames, List sharedElements, List 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);

    }

    });

    View full-size slide

  64. Add reveal for movie banner
    MovieDetailActivity.java
    toolbar.setVisibility(View.INVISIBLE);

    setEnterSharedElementCallback(new SharedElementCallback() {

    @Override

    public void onSharedElementEnd(List sharedElementNames, List sharedElements, List 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);

    }

    });

    View full-size slide

  65. Add reveal for movie banner
    MovieDetailActivity.java
    toolbar.setVisibility(View.INVISIBLE);

    setEnterSharedElementCallback(new SharedElementCallback() {

    @Override

    public void onSharedElementEnd(List sharedElementNames, List sharedElements, List 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);

    }

    });

    View full-size slide

  66. Add reveal for movie banner
    MovieDetailActivity.java
    toolbar.setVisibility(View.INVISIBLE);

    setEnterSharedElementCallback(new SharedElementCallback() {

    @Override

    public void onSharedElementEnd(List sharedElementNames, List sharedElements, List 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);

    }

    });

    View full-size slide

  67. Add reveal for movie banner
    MovieDetailActivity.java
    toolbar.setVisibility(View.INVISIBLE);

    setEnterSharedElementCallback(new SharedElementCallback() {

    @Override

    public void onSharedElementEnd(List sharedElementNames, List sharedElements, List 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);

    }

    });

    View full-size slide

  68. Activity Transitions
    - Easy to use once understand how it works
    - Limited customization due to TransitioGroup handling
    - Only available on Lollipop +

    View full-size slide

  69. THINK LIKE AN ANIMATOR
    The way you write your xml layout will directly affect how your
    Activity Transition Animations will work.

    View full-size slide

  70. https://github.com/marcospaulo/cinema_example
    Thank You
    Marcos Damasceno
    @marcospaulosd

    View full-size slide