Android’s ArcMotion — it could be better

Neil Davies
4 min readJan 19, 2018

In 2016 I decided to have a go at implementing this showreel in code:

tldr: Then, in 2016, ArcMotion didn’t work and wasn’t very flexible. Now it works for the above scenario, but is still not flexible and could be better.

The above showreel is the one where a FAB button drops down, in a curve, and uses a circular reveal to show some music playback controls. It seemed like a great way to learn more about animations in Android and explore what the framework could do.

The Android transition framework seemed like the best way to implement this. My plan was to to create two layouts, one for how the layout would look before the animation and one for how the layout would look after the animation. I could then create scenes and use a transition manager to create and play the animations. To create the curved motion I would need to use the ArcMotion class in a Change bounds transition.

The show stoppers

As I progressed I quickly found a few show stoppers. The first was that you should not use a CoordinatorLayout with the transition framework. They don’t play well together especially when you try and animate views that have been anchored to another view, as I had done with my FAB. At the time there wasn’t many good alternatives, but now there’s a newer layout that we can use instead that works well; the ConstraintLayout.

The second show stopper was animating the FAB along the curve. To do this I needed to use a change bounds transition that had a path motion. The specific type of the path motion was an ArcMotion, which should allow views moving from one point to another to move in a curve instead of a straight line.

The problems with the original ArcMotion in 2016 were :

  1. The algorithm did not describe a curve well — it just didn’t work in some cases!
  2. The algorithm tried to describe a curve above the line connecting the beginning and endpoints, instead of below the line.
  3. The algorithm does not work well when the start and endpoints are near horizontal or vertical and so additional parameters, min horizontal angle and min vertical angle, are needed.
Possible curved paths between two points. The larger the Arc angle the more curved the path

With the latest version of ArcMotion in 2018 some of these problems have been address. The algorithm has been improved, and if the endpoint is lower down the screen the curve used with be the one below the line connecting the start and endpoints.

So in short the new ArcMotion will generally work for above scenario, but it still has limitations. It still doesn’t work well if the start and endpoints are near vertical or horizontal and needs to use additional parameters to compensate for this. Additionally there is no way to explicitly state which of the two possible curved paths you want to use.

ArcMotionPlus

To address the problems with Android’s ArcMotion I created my own version called the ArcMotionPlus. I re-implemented the algorithm to calculate the control points of a cubic bezier curve and used Android’s Path class to generate the curve path with the method cubicTo. I also extracted the algorithm to a separate CubicBezierArc class so that it can be used to draw curves on a canvas or to generate a path that can be used by an ObjectAnimator

Using ArcMotionPlus is really straightforward. You just need to specify an angle , anything between 1 and 179 degrees, and state which curve you want it to follow between the two points by setting the reflected Arc parameter to true or false. Then it’s just a case of adding it to your Transition.

I’ve created a Sample app so others can explore how the to use the ArcMotionPlus and CubicBezierArc classes

The full source code for the sample app and some more explanations on how to use ArcMotionPlus and CubicBezierArc can be found here on my github page.

One thing to note, using cubic bezier curves to approximate a curve which describes a section of a circle works well up to about an angle of 90 degrees. Above this the curve will not exactly fit to a circle. This most probably isn’t much of a problem if you are moving an object along a curve, but if you are using the CubicBezierArc to draw curves on a canvas you most probably don’t want to go much past an angle of 90 degrees, otherwise you’ll start to notice the curve deviates from a circular path.

For a more detailed explanation of the maths behind cubic bezier curves check out this excellent link here

ArcMotionPlus in Action

Just to finish up here’s a gif of my Android implementation of the original showreel. It uses the ArcMotionPlus class and just a few other animations.

--

--