Thursday, July 15, 2010

Grow Your Container With This Fool Proof Method

Growing stuff is usually the subject filling my spambox... But into my inbox came a question from Terrence on how to grow a container.Generally what he wanted was an effect similar to the one found on Google maps (that you can see in the video right here).I tried to implement something like this in the most generic way possible which required a minor tweak to LWUIT (allowing us to restore the original preferred size of a component).

Generally the whole grow/shrink logic is contained in one method: "grow". Its relatively simple and just creates a motion between the current size of the component and the preferred size thus allowing the new component to "grow into place". The motion updates the preferred size and relayouts the form to create the smooth animation effect we see in the video.

I needed the ability to restore the default preferred size otherwise I would be stuck in the larger size after animating once. An alternative solution would have been to use a custom Container sublclass or to keep the original values stored neither one of which is my favorite...

Another "complexity" relates to the rather complex nature of preferred size, text area reports a relatively large preferred size before layout actually occurs. The reason is that it can't possibly know the target size of the container it will be placed in so it just guesses. So to support this situation I needed to layout the text area once in order to allow it to fit into place.

The code for this demo is in the incubator and pasted bellow:

publicclassGrowMidletextendsMIDlet{privatestaticfinalStringLONG_TEXT_1="There is some text that should take more than one line to show so it will be cut off at some point when shown in a single line but when we show it as multiline it should work out and layout just fine and dandy... ";privatestaticfinalStringLONG_TEXT_2="Growing text can be longer or shorter, it can be placed in the middle of the screen or anywhere really this is quite generic!";privatestaticfinalStringLONG_TEXT_3="Using this is as simple as pie with any container type you can think of and any text length!";publicvoidstartApp(){try{Display.init(this);Resourcesr=Resources.open("/pimpTheme.res");UIManager.getInstance().setThemeProps(r.getTheme(r.getThemeResourceNames()[0]));Formf=newForm("Grow Demo");f.addComponent(createGrowingContainer(LONG_TEXT_1, "TextAreaMe"));f.addComponent(createGrowingContainer(LONG_TEXT_2, "TextAreaThem"));f.addComponent(createGrowingContainer(LONG_TEXT_3, "TextAreaMe"));f.show();}catch(IOExceptionex){ex.printStackTrace();}}

publicvoidactionPerformed(ActionEventevt){growingContainer.removeAll();growingContainer.addComponent(BorderLayout.CENTER, multiLine);Containerflow=newContainer();if(shrink.getParent()!=null){shrink.getParent().removeAll();}flow.addComponent(shrink);growingContainer.addComponent(BorderLayout.SOUTH, flow);// the first time around the text area doesn't report the correct preferred size// since it doesn't know its screen placementif(firstTime){growingContainer.revalidate();}grow(growingContainer);growingContainer.revalidate();}});shrink.addActionListener(newActionListener(){