Fork us on GitHub

New Animation Manager

Rethinking animations in Codename One from the ground up
Post Image

New Animation Manager

We committed a major somewhat revolutionary change to how layout animations and the basic component tree work in Codename One. This is important to understand since it changes the very nature of how we expect components to behave in Codename One. This also allows us to create some pretty spectacular effects such as the ones in the title above.

There are several types of animations in Codename One:

  • Form/Dialog transitions
  • Replace transitions
  • Layout animations
  • Low level animations

Transitions and low level animations are both special cases that aren't affected by this change. However, replace transitions and layout animations have been effectively rewritten to use the new AnimationManger class. The AnimationManger class allows executing a component animation synchronously or asynchronously and starting with current builds all replace/layout animations (e.g. Container.replace, Container.animateLayout etc.) delegate their work to this class.

Broken Compatibility

This is important since some compatibility is broken as a result of this change!
One of the core problems with the old animation framework was that you can't have to animations going on at once e.g. if you did something like this:

myContainer.add(new Button("Button")).animateLayout(300);

This code could fail if you invoke it twice concurrently since there would be two animations mutating the container at the same time and they would not work in sequence!
A lot of developers assumed incorrectly that this code would fix this problem:

myContainer.add(new Button("Button")).animateLayoutAndWait(300);

Since the AndWait methods block the EDT they assume no other addition can happen during this time but the AndWait method doesn't block event dispatch so if a user triggers an event that triggers this code it could still fail. The workaround we often suggested was something like this:

if(!locked) {
    locked = true;
    myContainer.add(new Button("Button")).animateLayoutAndWait(300);
    locked = false;
} else {
    // postpone animation/addition

While this works it makes generic code difficult and has the side effect of only being aware of a specific change. So as part of this change we changed the very way add/remove component work in Codename One!
If you add a component and there is no animation it will work like it always did. However, if you add a component and there is an animation in progress the addition will be delayed to the end of the animation!
That might not produce the result you want but it will leave you with a valid UI and unlike some of the cases above it is unlikely to crash your application, which is probably the most important thing.


We didn't just do this to fix bugs though, we are looking at integrating some of the cool special effects you can see here:

This animation is a combination of a new ability to step thru animation stages when scrolling with a new "style animation" that accepts a destination UIID for a Component and morphs from the source style to the destination UIID. This specific demo includes this code:

Form hi = new Form("Shai's Social App", new BoxLayout(BoxLayout.Y_AXIS));
for(int iter = 0 ; iter < 100 ; iter++) {
    hi.add(new Label("Social Data Goes here..."));
Toolbar tb = new Toolbar();
ComponentAnimation cna = tb.createStyleAnimation("TitleAreaClean", 200);
ComponentAnimation title = tb.getTitleComponent().createStyleAnimation("TitleClean", 200);
hi.getAnimationManager().onTitleScrollAnimation(cna, title);;

The styling for both the source title with my picture and the destination clean styles are defined in the theme but you can also define the source style in code.

Share this Post:

Posted by Shai Almog

Shai is the co-founder of Codename One. He's been a professional programmer for over 25 years. During that time he has worked with dozens of companies including Sun Microsystems.
For more follow Shai on Twitter & github.