Trong bài viết này, tôi xin được giới thiệu đến các bạn cách tạo ra TabMenu. Các component của chúng ta sẽ hỗ trợ:

Các style của Tab: màu nền, màu chữ, font, padding.

Tự động cuộn ngang màn hình mà không cần phải quan tâm tới độ rộng màn hình.

Đầu tiên, ta có các biến về style của Tab:

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;


Sau đó, chúng ta tiếp tục định nghĩa các biến để lưu trạng thái của TabMenu:

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

Tiếp theo, chúng ta sẽ xây dựng Constructor của TabMenu với 2 tham số: label của các tab và độ rộng viewport của từng tab.

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;
            }
      }
}

Tiếp theo, bạn định nghĩa phương thức utility để kiểm tra xem Tab có visible hay không

private boolean isTabVisible(int tabIndex)
{
      return tabsLeft[tabIndex] < viewportX + viewportWidth &&
            tabsLeft[tabIndex] + tabsWidth[tabIndex] >= viewportX;
}

Bây giờ, chúng ta sẽ tiếp tục tạo ra các phương thức dùng để cuộc hay chuyển đổi qua lại giữa các Tab

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));
      }
}

Nhiêm vụ cuối cùng là chúng ta sẽ vẻ chúng lên màn hình

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;
      }
}

Code được tham khảo từ forum Nokia

Code download

Bạn thấy bài viết này thế nào?