Tuesday, June 17, 2008

Implementing A Selected Item Ticker In A List


A discussion came up in the LWUIT forum/list regarding animating list items e.g. ticker functionality where the selected element in the list is animated. This is a confusing subject because the renderer paradigm inspired by Swing doesn't allow a state and thus doesn't allow animations. So the List component itself must be animated. However if you want to animate a specific item you must implement the animation logic in the renderer code thus decoupling the functionality.
This is a bit counter intuitive but there are complexities when creating an efficient/scalable list thats infinitely customizable... Once you accept the basic premise of renderers this approach makes allot of sense.

Notice that the renderer in the code bellow is not really animated but rather allows the list (which is) to paint its state. Also notice that the list animate() method takes care to invoke its super class otherwise list traversal animations would break.
Form f = new Form("Ticker List");
class TickerRenderer extends DefaultListCellRenderer {
private int position;
public void resetPosition() {
position = 0;
}
public void incrementPosition() {
position += 5;
}

public void paint(Graphics g) {
if(hasFocus()) {
String text = getText();
Style s = getStyle();
int width = s.getFont().stringWidth(text);
if(getWidth() >= width) {
super.paint(g);
return;
}
UIManager.getInstance().getLookAndFeel().setFG(g, this);
int actualPosition = position % width;
g.translate(-actualPosition, 0);
g.drawString(text, getX() + s.getPadding(LEFT), getY());
g.translate(width + 20, 0);
g.drawString(text, getX(), getY());
g.translate(actualPosition - 20 - width , 0);
} else {
super.paint(g);
}
}

public Component getListCellRendererComponent(List list, Object value, int index, boolean isSelected) {
super.getListCellRendererComponent(list, value, index, isSelected);
return this;
}
}
final TickerRenderer renderer = new TickerRenderer();
List myList = new List(new String[] {"First", "Second", "Really long string that goes on and on and on and on and on and on",
"and on and on and on and on and on and on and on and on and on and on and on and on",
"Well enough already with the damn long strings this is really getting old...",
"A B C D E F G H I J K L M N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 8 9 !!!!....."}) {
private long tickTime = System.currentTimeMillis();
private int lastSelection = -1;
public boolean animate() {
boolean val = super.animate();
if(hasFocus()) {
long currentTime = System.currentTimeMillis();
if(currentTime - tickTime > 300) {
if(lastSelection == getSelectedIndex()) {
renderer.incrementPosition();
} else {
lastSelection = getSelectedIndex();
renderer.resetPosition();
}
return true;
}
}
return val;
}
};
myList.setListCellRenderer(renderer);
f.setLayout(new BorderLayout());
f.addComponent(BorderLayout.CENTER, myList);
f.show();

0 comments:

Post a Comment