GithubHelp home page GithubHelp logo

tchigher / animation-tutorials Goto Github PK

View Code? Open in Web Editor NEW

This project forked from smarttoolfactory/animation-tutorials

0.0 0.0 0.0 48.67 MB

๐Ÿญ๐Ÿš€๐Ÿ’— Tutorials about animations with Animators, Animated Vector Drawables, Shared Transitions, and more

Kotlin 91.69% Java 8.31%

animation-tutorials's Introduction

๐Ÿญ๐Ÿš€๐Ÿ’— Animation Tutorials

Tutorials about animations in Android such as ObjectAnimators, ValueAnimators, translations, gradient animations, AnimationDrawables, AnimatedVectorDrawables with states, physics animations, fragment transitions and image to ViewPager transitions and more.

Overview

  • Tutorial1-1Basics
    Tutorials about animators, animation basics and using coroutine based SurfaceView to create a counter up down motion
Ch2-3 Circular Reveal Ch2-4 Rotate X/Y Flip Ch2-6 Zoom
Ch2-7 Gradient Ch2-8 Counter TextViews Ch2-9 Counter SurfaceView
Ch3-1 Physics Ch3-2 Scale and Chained Ch3-3 Fling Ch3-4 BNV+TabLayout Physics

Ch1-1 Animated VDs Ch1-2 State Change Ch1-3 BNV Icons
Ch1-2 RV Transition Ch1-4 RV to VP2 Transition Ch2-3 Nav Components

Physics Based Animations

Physics-based motion is driven by force. Spring force is one such force that guides interactivity and motion. A spring force has the following properties: damping and stiffness. In a spring-based animation, the value and the velocity are calculated based on the spring force that are applied on each frame.

If you'd like your app's animations to slow down in only one direction, consider using a friction-based fling animation instead.

Build a spring animation

The general steps for building a spring animation for your application are as follows:

  • Add the support library You must add the support library to your project to use the spring animation classes.
  • Create a spring animation: The primary step is to create an instance of the SpringAnimation class and set the motion behavior parameters.
  • (Optional) Register listeners: Register listeners to watch for animation lifecycle changes and animation value updates.

Note: Update listener should be registered only if you need per-frame update on the animation value changes. An update listener prevents the animation from potentially running on a separate thread.

  • (Optional) Remove listeners: Remove listeners that are no longer in use.
  • (Optional) Set a start value: Customize the animation start value.
  • (Optional) Set a value range: Set the animation value range to restrain values within the minimum and the maximum range.
  • (Optional) Set start velocity: Set the start velocity for the animation.
  • (Optional) Set spring properties: Set the damping ratio and the stiffness on the spring.
  • (Optional) Create a custom spring: Create a custom spring in case you do not intend to use the default spring or want to use a common spring throughout the animation.
  • Start animation: Start the spring animation.
  • (Optional) Cancel animation: Cancel the animation in case the user abruptly exits the app or the view becomes invisble.

Drawable Animations

XML for the VectorDrawable containing properties to be animated

A VectorDrawable can be represented in xml with

<vector xmlns:android="http://schemas.android.com/apk/res/android"
      android:height="64dp"
      android:width="64dp"
      android:viewportHeight="600"
      android:viewportWidth="600" >
      <group
          android:name="rotationGroup"
          android:pivotX="300.0"
          android:pivotY="300.0"
          android:rotation="45.0" >
          <path
              android:name="v"
              android:fillColor="#000000"
              android:pathData="M300,70 l 0,-70 70,70 0,0 -70,70z" />
      </group>
  </vector>

where width and height are the actual dimensions of while viewportWidth, and viewportHeight are used for drawing coordinates.

M(x,y) Begin a new subpath by moving to (x,y).

L(x,y) Draw a line to (x,y).

C (x1,y1 x2,y2 x,y) Draw a cubic bezier curve to (x,y) using control points (x1,y1) and (x2,y2).

Z Close the path by drawing a line back to the beginning of the current subpath

group tag is used for grouping sections of drawable to be able to be animated together. And some animations such as rotation, and translation can only be applied to groups.

Animations can be performed on the animatable attributes in android.graphics.drawable.VectorDrawable. These attributes will be animated by android.animation.ObjectAnimator. The ObjectAnimator's target can be the root element, a group element or a path element. The targeted elements need to be named uniquely within the same VectorDrawable. Elements without animation do not need to be named.

For more details you can check out here

XML for AnimatedVectorDrawable

An AnimatedVectorDrawable element has a VectorDrawable attribute, and one or more target element(s). The target element can specify its target by android:name attribute, and link the target with the proper ObjectAnimator or AnimatorSet by android:animation attribute.

๐Ÿ”ฅ๐Ÿ˜ ShapeShifter by Alex Lockwood makes it so easy to create animations for Vector Drawables. Wonderful and very easy to use tool to create Animated Vector Drawables.

XML for Animations defined using ObjectAnimator or AnimatorSet

<set xmlns:android="http://schemas.android.com/apk/res/android">
      <objectAnimator
          android:duration="3000"
          android:propertyName="pathData"
          android:valueFrom="M300,70 l 0,-70 70,70 0,0 -70,70z"
          android:valueTo="M300,70 l 0,-70 70,0  0,140 -70,0 z"
          android:valueType="pathType"/>
</set>

Define an AnimatedVectorDrawable all in one XML file

Since the AAPT tool supports a new format that bundles several related XML files together, we can merge the XML files from the previous examples into one XML file:

<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
                   xmlns:aapt=&quothttp://schemas.android.com/aapt" >
      <aapt:attr name="android:drawable">
          <vector
              android:height="64dp"
              android:width="64dp"
              android:viewportHeight="600"
              android:viewportWidth="600" >
              <group
                  android:name="rotationGroup"
                  android:pivotX="300.0"
                  android:pivotY="300.0"
                  android:rotation="45.0" >
                  <path
                      android:name="v"
                      android:fillColor="#000000"
                      android:pathData="M300,70 l 0,-70 70,70 0,0 -70,70z" />
              </group>
          </vector>
      </aapt:attr>
 
      <target android:name="rotationGroup"> *
          <aapt:attr name="android:animation">
              <objectAnimator
              android:duration="6000"
              android:propertyName="rotation"
              android:valueFrom="0"
              android:valueTo="360" />
          </aapt:attr>
      </target>
 
      <target android:name="v" >
          <aapt:attr name="android:animation">
              <set>
                  <objectAnimator
                      android:duration="3000"
                      android:propertyName="pathData"
                      android:valueFrom="M300,70 l 0,-70 70,70 0,0 -70,70z"
                      android:valueTo="M300,70 l 0,-70 70,0  0,140 -70,0 z"
                      android:valueType="pathType"/>
              </set>
          </aapt:attr>
       </target>
  </animated-vector>

Shared Transitions

Transitions

To create transition between views set transition name in xml with android:transitionName

 <androidx.appcompat.widget.AppCompatImageView
            // Rest of the imageView properties
            android:transitionName="ivAvatar"/>

or in Kotlin/Java with

iv.setTransitionName("SOME_TRANSITION_NAME")

these names should match for both Activities. To start transition after a click

 val intent = Intent(this, Activity1_1DetailActivity::class.java)
        intent.putExtra("imageRes", imageRes)

        // create the transition animation - the images in the layouts
        // of both activities are defined with android:transitionName="robot"
        val options = ActivityOptions
            .makeSceneTransitionAnimation(
                this,
                ivAvatar,
                ViewCompat.getTransitionName(ivAvatar)
            )
        // start the new activity
        startActivity(intent, options.toBundle())

For custom transitions create transition folder inside res folder and add

<slide xmlns:android="http://schemas.android.com/apk/res/android"
    android:slideEdge="left"
    android:duration="1500">

    <targets>
        <!-- Specify the status bar ID if it needs to be excluded -->
        <target android:excludeId="@android:id/statusBarBackground"/>
        <!-- Specify the navigation bar ID if it needs to be excluded -->
        <target android:excludeId="@android:id/navigationBarBackground"/>
    </targets>

</slide>

default transition for Android system is

<transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- This is the systems default transition -->
    <changeBounds />
    <changeTransform />
    <changeClipBounds />
    <changeImageTransform />
</transitionSet>

Use <item name="android:windowContentTransitions">true</item> to enable Activity transitions Use <item name="android:windowSharedElementsUseOverlay">false</item> for shared transition items not to be drawn over NavigationBar, or Toolbar

Transition Callbacks and Lifecycles

  • Note Exit-ReEnter transitions, and ReEnter-Return transitions for Activity are same transition by default.
  • Exit, Enter, ReEnter and Return transitions are NULL for fragments by default
  • setExitSharedElementCallback, and sharedElementExitTransition useful for changing shared transition elements that are mapped with String and View. For instance, after transition from RecyclerView to ViewPager or another RecyclerView, user changes the selected page/element and we remap the shared element for the next imageView in ViewPager's current page.

Transition change states and ordering for transitions Between Activities

ExitSharedElementCallback is triggered in first Activity, in second Activity EnterSharedElementCallback is triggered

        Activity1 ---> Activity2
        Exit    ----> Enter
        SharedElementCallback Order: Activity1 Exit -> Activity2 Enter

        I: ๐ŸŒฝ Activity1_1Basics: setExitSharedElementCallback() names:[transition_image_view], sharedElements: {transition_image_view=androidx.appcompat.widget.AppCompatImageView{b3a80cf V.ED..... ...P.... 21,21-231,231 #7f0800c5 app:id/ivPhoto}}
        I: ๐Ÿ”ฅ Activity1_1Basics: sharedElementExitTransition onTransitionStart()

        I: ๐Ÿ’ Activity1_1Details: setEnterSharedElementCallback() names:[transition_image_view], sharedElements: {transition_image_view=androidx.appcompat.widget.AppCompatImageView{11b033f V.ED..... ......ID 0,0-1080,810 #7f0800c4 app:id/ivPhoto}}
        I: ๐ŸšŒ Activity1_1Details: sharedElementEnterTransition onTransitionStart()

        Activity1 <-- Activity2
        ReEnter <--- Return
        SharedElementCallback Order: Activity2 Exit -> Activity1 Enter
        I: ๐Ÿ’ Activity1_1Details: setEnterSharedElementCallback() names:[transition_image_view], sharedElements: {transition_image_view=androidx.appcompat.widget.AppCompatImageView{11b033f V.ED..... ........ 0,0-1080,810 #7f0800c4 app:id/ivPhoto}}
        I: ๐ŸŒฝ Activity1_1Basics: setExitSharedElementCallback() names:[transition_image_view], sharedElements: {transition_image_view=androidx.appcompat.widget.AppCompatImageView{b3a80cf V.ED..... ......ID 21,21-231,231 #7f0800c5 app:id/ivPhoto}}

        I: ๐Ÿš• Activity1_1Details: sharedElementReturnTransition onTransitionStart()
        I: ๐Ÿ Activity1_1Basics: sharedElementReenterTransition onTransitionStart()


        onMapSharedElements() does exact same thing in makeSceneTransitionAnimation
        mapping string to view or with Pair<View, String>

Fragment Shared Element Transitions

  • ๐Ÿ”ฅ๐Ÿ”ฅ๐Ÿ”ฅ Make sure that you are importing androidx.transition, do NOT import android.transition components, mixing different import packages causes Wrong Transition Exception

  • exitTransition, enterTransition, returnTransition and reEnterTransitions are null for fragments by default.

  • ๐Ÿ”ฅ๐Ÿ”ฅ Setting allowReturnTransitionOverlap to false lets this fragment's reenterTransition to wait previous fragment's returnTransition to finish

  • add sharedElement to fragments with addSharedElement(ivPhoto, ivPhoto.transitionName) and use setReorderingAllowed(true) to optimize for shared element transition

  • With Navigation Components set shared elements as

val direction: NavDirections =
    Fragment2_3MagazineListDirections.actionFragment23MagazineListToFragment23MagazineDetail(
        magazineModel
    )

val extras = FragmentNavigatorExtras(
    binding.ivMagazineCover to binding.ivMagazineCover.transitionName,
)

findNavController().navigate(direction, extras)
  • ๐Ÿ”ฅ๐Ÿ”ฅ๐Ÿ”ฅ With transitions, it's required for start and end values to be different from each other to call createAnimator method.

To make sure that it gets called, either set captureStartValues and captureEndValues manually, or in fragment transitioned to, create ** setEnterSharedElementCallback** and override onSharedElementStart and onSharedElementEnd methods and set properties of objects that are not shared in both fragments.

Without doing this enter or exit might not work because of Transition start and end point to same value.

Resources and References

Wonderful and very helpful resources, check them out ๐Ÿคฉ๐Ÿ˜

CodeLab Property Animation
Android Design Patterns
android/animation-samples: Multiple samples showing the best practices in animation on Android
Playing with Material Design Transitions โœจ | by Philippe BOISNEY | ProAndroidDev
Meaningful Motion: Circular Reveal & Shared Elements | by Jossi Wolf | Snapp Mobile | Medium
Custom Transitions in Android. Since Android API 19 Google provides aโ€ฆ | by Roman Bielokon | Medium
Propagating Transitions in Android | by Nick Cruz | ProAndroidDev
Shared Element Transition using fragments Android | Developers Breach
Fragment Transitions
Circular reveal animation between Fragments | by Gabor Novak | Medium
Reveal Transition
Plaid App

TODOs:

  • Add RecyclerView, ViewPager animations
  • Add custom Views with animations

animation-tutorials's People

Contributors

smarttoolfactory avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.