Wednesday, June 15, 2011

LWUIT's New Layout Animation Facility


I'd like to create some more demo animations and some additional animation utilities like this one and I probably will as soon as I get some time.

While the animations in this video might seem elaborate, they are really simple to achieve and work great even on feature phones. All that is really needed is one LWUIT method: Container.animateLayout(int)

To understand this I'll just explain a couple of things about LWUIT components, when we add a component to a container its generally just added but not positioned anywhere. A novice might notice the setX/Y/Width/Height methods on a component and just try to position it absolutely.
This won't work since these methods are meant for the layout manager which it implicitly invoked when a form is shown (internally in LWUIT) and the layout manager uses these methods to position the components as it sees fit.
However, if you add components to LWUIT on your own it is your responsibility to invoke revalidate (or layoutContainer) to arrange the newly added components. LWUIT doesn't "reflow" implicitly since that would be hugely expensive, imagine doing the layout calculations for every component added to the container the cost would be closer to a factorial of the original cost of adding a component.

The animateLayout() is simply a fancy form of revalidate. After changing the layout when you invoke this method it will animation the components to their new sizes and positions seamlessly.

The first example in the tipster demo shows an "interlace" effect where the components each slide from a separate direction into the screen.  This is the code I used before showing the form:

        f.revalidate();
        for(int iter = 0 ; iter < c.getComponentCount() ; iter++) {
            Component current = c.getComponentAt(iter);
            if(iter % 2 == 0) {
                current.setX(-current.getWidth());
            } else {
                current.setX(current.getWidth());
            }
        }
        c.setShouldCalcPreferredSize(true);
        c.animateLayout(1000);

Lets go over this line by line:

        f.revalidate();
I make sure the layout is valid so I can start from the correct component positions.

            if(iter % 2 == 0) {
                current.setX(-current.getWidth());
            } else {
                current.setX(current.getWidth());
            }
I manually position every component outside of the screen, if they are odd I place them to the right and if they are even I place them to the left.



        c.setShouldCalcPreferredSize(true);
I mark the UI as needing layout. This is crucial since I validated the UI earlier (by calling revalidate). Changing the X/Y/Width/Height doesn't trigger a validation! LWUIT doesn't know I made that change!
By calling setShouldCalcPreferredSize I'm explicitly telling LWUIT that I changed something in the UI and I want it to validate, normally this method is implicitly invoked by LWUIT.

        c.animateLayout(1000);
Perform the animation over the length of a second, this might seem like much but the animation starts before the form entry transition so it isn't that much.

The other animations are even simpler than this one and all follow the same basic rules, place the components wherever you want either manually (or by changing the layout) and use animateLayout() to automatically rearrange them to the new position.


BTW we fully intended to have a new LWUIT release by now but its getting delayed due to the typical bureaucratic nonsense that is an unavoidable reality within a large corporation. We apologize it is taking so long and even more so that we do not have an ETA. Those of you following the SVN know we already have everything ready for 1.5.

2 comments:

  1. Bravo ,I try it so nice ...

    go lwuit team go

    need more animation

    ReplyDelete
  2. Really great post by shai and this post is very helpful
    thanks
    arvind

    ReplyDelete