Categories: Java ME | Code Examples | UI
We will build a reusable Tabbed Menu using J2ME.
You can find a midlet showing this component in action here.
Our component will support:
Let's start from the customizable variables, whose aim is self-explaining:
int background = 0xffffff; int bgColor = 0xcccccc; int bgFocusedColor = 0x0000ff; int foreColor = 0x000000; int foreFocusedColor = 0xffffff; int cornerRadius = 4; int padding = 2; int margin = 2; Font font = Font.getDefaultFont(); int scrollStep = 20;
Then we'll define some internal variables, used to mantain the tabbed menu state:
int selectedTab = 0; //selected tab index int[] tabsWidth = null; //width of single tabs int[] tabsLeft = null; //left X coordinate of single tabs int tabHeight = 0; //height of tabs (equal for all tabs) String[] tabs = null; //tab labels int menuWidth = 0; //total menu width int viewportWidth = 0; //visible viewport width int viewportX = 0; //current viewport X coordinate
Now, we'll define a simple constructor accepting tab labels and viewport width as parameters:
public TabMenu(String[] tabs, int width) { this.tabs = tabs; this.viewportWidth = width; initialize(); } void initialize() { tabHeight = font.getHeight() + cornerRadius + 2 * padding; menuWidth = 0; tabsWidth = new int[tabs.length]; tabsLeft = new int[tabs.length]; for(int i = 0; i < tabsWidth.length; i++) { tabsWidth[i] = font.stringWidth(tabs[i]) + 2 * padding + 2 * cornerRadius; tabsLeft[i] = menuWidth; menuWidth += tabsWidth[i]; if(i > 0) { menuWidth += margin; } } }
Now, let's define an utility method to check if a tab is visible or not.
private boolean isTabVisible(int tabIndex) { return tabsLeft[tabIndex] < viewportX + viewportWidth && tabsLeft[tabIndex] + tabsWidth[tabIndex] >= viewportX; }
And now we'll implement the tab switching/scrolling methods, that will use the isTabVisible method defined above:
public void goRight() { go(+1); } public void goLeft() { go(-1); } private void go(int delta) { int newTab = Math.max(0, Math.min(tabs.length - 1, selectedTab + delta)); boolean scroll = true; if(newTab != selectedTab && isTabVisible(newTab)) { selectedTab = newTab; if( (delta > 0 && tabsLeft[selectedTab] + tabsWidth[selectedTab] > viewportX + viewportWidth) || (delta < 0 && tabsLeft[selectedTab] < viewportX)) { scroll = true; } else { scroll = false; } } if(scroll) { viewportX = Math.max(0, Math.min(menuWidth - viewportWidth, viewportX + delta * scrollStep)); } }
And now, we're ready to paint our menu :)
public void paint(Graphics g) { int currentX = - viewportX; g.setClip(0, 0, viewportWidth, tabHeight); g.setColor(background); g.fillRect(0, 0, viewportWidth, tabHeight); for(int i = 0; i < tabs.length; i++) { g.setColor(i == selectedTab ? bgFocusedColor : bgColor); g.fillRoundRect(currentX, 0, tabsWidth[i], tabHeight + cornerRadius, 2 * cornerRadius, 2 * cornerRadius); g.setColor(i == selectedTab ? foreFocusedColor : foreColor); g.drawString(tabs[i], currentX + cornerRadius + padding, cornerRadius + padding, Graphics.LEFT | Graphics.TOP); currentX += tabsWidth[i] + margin; } }
You can download source code of TabMenu here: