Monday, July 21, 2008

Pimp My LWUIT Part III: ScrollBar Part A

Lots of components in LWUIT are ugly by default and need a theme to realize their full potential, but none are as ugly as the scrollbar is by default... We MUST fix that for a decent scrolling experience and LWUIT gives us all the tools to do so.

Ideally replacing the scrollbar should be easier and in a future revision I would like to do so but that would require some changes that aren't trivial. Right now the only way to replace the scroll bar is to draw it using the look and feel, since we already derived the look and feel class this is no problem for us...

This is a rather elaborate scroll bar which I created based on the Aerith demo, I draw it using the an image for the up/down arrow and use drawing primitives to fill the center. I only implemented support for vertical scrollbars here for the sake of simplicity, the work required for horizontal bars is practically identical.

I started by adding a few buttons to my MIDlet:
for(int iter = 0 ; iter < 30 ; iter++) {
helloForm.addComponent(new Button("Scrolling " + iter));
}

I then went on to the look and feel where I initialized the images for the scroll representing the up/down arrows :
public class PimpLookAndFeel extends DefaultLookAndFeel {
private static final Image SCROLL_DOWN;
private static final Image SCROLL_UP;

static {
Image sd = null;
Image su = null;
try {
sd = Image.createImage("/scrollbar-button-south.png");
su = Image.createImage("/scrollbar-button-north.png");
} catch(IOException ioErr) {
ioErr.printStackTrace();
}
SCROLL_DOWN = sd;
SCROLL_UP = su;
}
What remains is indicating the size of the scrollbar and just drawing it when requested to do so by the underlying platform which is pretty standard LWUIT drawing code:
    private void drawScrollImpl(Graphics g, Component c, float offsetRatio, int blockSize, boolean vertical) {
int x = c.getX();
int y = c.getY();
int width, height, aX, aY, bX, bY;
width = SCROLL_UP.getWidth();
int margin = 0;
aX = x + c.getWidth() - width - margin;
x = aX;
bX = aX;
aY = y + margin;
bY = y + c.getHeight() - margin - SCROLL_UP.getHeight();
y = aY + SCROLL_UP.getHeight();
height = c.getHeight() - SCROLL_UP.getHeight() * 2;
g.setColor(0xffffff);
g.fillRect(x, y, width, height);
g.drawImage(SCROLL_UP, aX, aY);
g.drawImage(SCROLL_DOWN, bX, bY);

g.setColor(0xcccccc);
g.fillRoundRect(x + 2, y + 2, width - 4, height - 4, 10, 10);
g.setColor(0x333333);
int offset = (int)(height * offsetRatio);
g.fillRoundRect(x + 2, y + 2 + offset, width - 4, height / 3, 10, 10);
}

/**
* Draws a vertical scoll bar in the given component
*/

public void drawVerticalScroll(Graphics g, Component c, float offsetRatio, float blockSizeRatio) {
int blockSize = (int)(c.getHeight() * blockSizeRatio);
drawScrollImpl(g, c, offsetRatio, blockSize, true);
}

/**
* Scrollbar is drawn on top of existing widgets
*/

public int getVerticalScrollWidth() {
return SCROLL_UP.getWidth();
}

/**
* Scrollbar is drawn on top of existing widgets
*/

public int getHorizontalScrollHeight() {
return 0;
}
}

3 comments:

  1. Hello Shay.
    I have tested your code and the scroll bars` seemed not to be with the correct size, so I changed the last line of the drawScrollImpl method everything was OK:

    g.fillRoundRect(x + 2, y + 2 + offset, width - 4, (((height - 4) * blockSize) / c.getHeight()), 10, 10);

    hugs
    Rafael Quintana
    quintana@mobits.com.br

    ReplyDelete
  2. hi guys can u give me the full coding for the scrolling and how to add that into the form, this is my mail id kaalaththy21@gmail.com

    ReplyDelete
  3. It is now possible to customize the scrollbars via the theme entirely.

    ReplyDelete