如何编写多页标签页 Tab Control组件,附全部代码

OS 5.0的黑莓平台没有提供多页标签栏,下面我们来实现一个。

 

效果如下图,三个栏目,选择不同的栏目(TabItem),下面的内容不同(Manager)。

 

标签页是用一个定制的Field   TabItem,在paint()方法中根据该Field是focus与否的状态选择显示不同的背景图片。

 

标签页被选中的时候,调用fieldChangeNotify( 0 )方法通知TabControl窗口需要更换标签页下面的manager显示不同的内容。

 

 

 

 

 

代码中用到的三个资源文件:

tabitem_default.png   ,注意图片的右边,是有个凹陷的效果

 

tabitem_selected.png,和上面的图片是相同大小,但是颜色是白色的,右边有个竖线

 

table_background.png,这张图片将被铺满整条横向的Tab栏目。

 

 

 

详细代码如下:

TabControl.java

TabItem.java

BaseButtonField.java

 package cn.rim.samples.tabcontrol;

import net.rim.device.api.system.Bitmap;
import net.rim.device.api.system.Display;
import net.rim.device.api.ui.Field;
import net.rim.device.api.ui.Manager;
import net.rim.device.api.ui.decor.Background;
import net.rim.device.api.ui.decor.BackgroundFactory;

public class TabControl extends Manager {

 public TabControl() {
  super(0);
  Background bitmapBackground = BackgroundFactory.createBitmapBackground(Bitmap.getBitmapResource("table_background.png"));
  setBackground(bitmapBackground);
 }


 public int getPreferredWidth() {
  return Display.getWidth();
 }

 public int getPreferredHeight() {
  if (getFieldCount()>0)
   return getField(0).getPreferredHeight();
  else
   return 5;
 }

 protected void sublayout(int width, int height) {
     int x = 0;
     int y = 0;
     Field field;
     int numberOfFields = getFieldCount();
     for (int i=0; i<numberOfFields; ++i) {
        field = getField(i);
        setPositionChild(field, x, y);
        layoutChild(field, width, height);
       
        x += field.getPreferredWidth();
     }
     setExtent(getPreferredWidth(), getPreferredHeight());
 }
 
    protected boolean navigationMovement ( int dx, int dy, int status, int time ) {
       
        int focusIndex = getFieldWithFocusIndex();
     int columns = getFieldCount();
        if (dx > 0 ) { //向右滚动
         if ( focusIndex < columns-1 ) {
                getField(focusIndex+1).setFocus();
                return true;
         }else {
                getField(0).setFocus();
                return true;
         }
        }
        if (dx < 0) {//向左滚动
         if ( focusIndex ==0 ) {
                getField(columns-1).setFocus();
                return true;
         }else {
                getField(focusIndex-1).setFocus();
                return true;
         }
        }
       
        //向上向下的滚动这里就不做处理了
        return false;
    }
}

 

--------------------------------------------------------------------------------------------------------

package cn.rim.samples.tabcontrol;

import net.rim.device.api.system.*;
import net.rim.device.api.ui.*;

public class TabItem extends BaseButtonField
{
    private Bitmap[] _bitmaps;
    private static final int NORMAL = 0;
    private static final int FOCUS = 1;
   
    private String text; //标签栏文字
/*   
    public BitmapButtonField( Bitmap normalState )
    {       
        this( normalState, normalState, 0 );
    }
*/   
    public TabItem( Bitmap normalState, Bitmap focusState )
    {       
        this( normalState, focusState, 0 );
    }
   
    public TabItem( Bitmap normalState, Bitmap focusState, long style )
    {       
        super( Field.FOCUSABLE | style );
       
        if( (normalState.getWidth() != focusState.getWidth())
            || (normalState.getHeight() != focusState.getHeight()) ){
           
            throw new IllegalArgumentException( "Image sizes don't match" );
        }
       
        _bitmaps = new Bitmap[] { normalState, focusState };
    }
   
    //Yang Jiang
    public void setText(String value) {
     this.text = value;
    }
   
    public void setImage( Bitmap normalState ){
        _bitmaps[NORMAL] = normalState;
        invalidate();
    }
   
    public void setFocusImage( Bitmap focusState ){
        _bitmaps[FOCUS] = focusState;
        invalidate();
    }
   
    public int getPreferredWidth() {
        return _bitmaps[NORMAL].getWidth();
    }
   
    public int getPreferredHeight() {
        return _bitmaps[NORMAL].getHeight();
    }
   
    protected void layout( int width, int height ) {
        setExtent( _bitmaps[NORMAL].getWidth(), _bitmaps[NORMAL].getHeight() );
    }
   
    protected void paint( Graphics g ) {
        int index = g.isDrawingStyleSet( Graphics.DRAWSTYLE_FOCUS ) ? FOCUS : NORMAL;
        g.drawBitmap( 0, 0, _bitmaps[index].getWidth(), _bitmaps[index].getHeight(), _bitmaps[index], 0, 0 );
  g.drawText(text, 0, this.getHeight()/2,
    Graphics.VCENTER | Graphics.HCENTER, this.getWidth());
    }
   
    /**
     * With this commented out the default focus will show through
     * If an app doesn't want focus colours then it should override this and do nothing
     **/
    /*
    protected void paintBackground( Graphics g ) {
        // Nothing to do here
    }
    */
   
    protected void drawFocus( Graphics g, boolean on ) {
        // Paint() handles it all
        g.setDrawingStyle( Graphics.DRAWSTYLE_FOCUS, true );
        paintBackground( g );
        paint( g );
    }
}

 

--------------------------------------------------------------------------------------------------------

package cn.rim.samples.tabcontrol;

import net.rim.device.api.system.*;
import net.rim.device.api.ui.*;


/**
 * Implements all the stuff we don't want to do each time we need a new button
 */
public abstract class BaseButtonField extends Field
{
    private XYRect _drawFocusTempRect = new XYRect();
   
    public BaseButtonField()
    {
        this( 0 );
    }
   
    public BaseButtonField( long style )
    {       
        super( Field.FOCUSABLE | style );
    }
       
    protected void layout( int width, int height )
    {
        setExtent( 10, 10 );
    }
   
    protected void drawFocus( Graphics g, boolean on )
    {
        getFocusRect( _drawFocusTempRect );
   
        boolean oldDrawStyleFocus = g.isDrawingStyleSet( Graphics.DRAWSTYLE_FOCUS );
        boolean notEmpty = g.pushContext( _drawFocusTempRect.x, _drawFocusTempRect.y, _drawFocusTempRect.width, _drawFocusTempRect.height, 0, 0 );

        try {
            if( notEmpty ) {
                g.setDrawingStyle( Graphics.DRAWSTYLE_FOCUS, on );
                paintBackground( g );
                paint( g );
            }
        } finally {
            g.popContext();
            g.setDrawingStyle( Graphics.DRAWSTYLE_FOCUS, oldDrawStyleFocus );
        }
    }
   
    protected boolean keyChar( char character, int status, int time )
    {
        if( character == Characters.ENTER ) {
            clickButton();
            return true;
        }
        return super.keyChar( character, status, time );
    }
   
    protected boolean navigationClick( int status, int time )
    {
        clickButton();
        return true;   
    }
   
    protected boolean trackwheelClick( int status, int time )
    {       
        clickButton();   
        return true;
    }
   
    protected boolean invokeAction( int action )
    {
        switch( action ) {
            case ACTION_INVOKE: {
                clickButton();
                return true;
            }
        }
        return super.invokeAction( action );
    }   

    public void setDirty( boolean dirty ) {
        // We never want to be dirty or muddy
    }
    
    public void setMuddy( boolean muddy ) {
        // We never want to be dirty or muddy
    }
        
    /**
     * A public way to click this button
     */
    public void clickButton()
    {
        fieldChangeNotify( 0 );
    }
}

--------------------------------------------------------------------------------------------------------

package cn.rim.samples.tabcontrol;

import net.rim.device.api.system.Bitmap;
import net.rim.device.api.ui.Color;
import net.rim.device.api.ui.Field;
import net.rim.device.api.ui.FocusChangeListener;
import net.rim.device.api.ui.Manager;
import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.ui.component.LabelField;
import net.rim.device.api.ui.component.SeparatorField;
import net.rim.device.api.ui.container.HorizontalFieldManager;
import net.rim.device.api.ui.container.MainScreen;
import net.rim.device.api.ui.container.VerticalFieldManager;
import net.rim.device.api.ui.decor.Background;
import net.rim.device.api.ui.decor.BackgroundFactory;

public class DemoApp extends UiApplication {

 public DemoApp() {
  TabControlScreen screen = new TabControlScreen();
  pushScreen(screen);
 }

 /**
  * @param args
  */
 public static void main(String[] args) {
  DemoApp app = new DemoApp();
  app.enterEventDispatcher();
 }

 private class TabControlScreen extends MainScreen implements FocusChangeListener {

  private TabItem tab1;
  private TabItem tab2;
  private TabItem tab3;

  private Manager tabArea;

  private Manager tab1Manager;
  private Manager tab2Manager;
  private Manager tab3Manager;
  

  public TabControlScreen() {
   TabControl tabcontrol = new TabControl();
  
   tab1 = new TabItem(Bitmap.getBitmapResource("tabitem_default.png"), Bitmap.getBitmapResource("tabitem_selected.png"));
   tab1.setText("Page 1");
   tab2 = new TabItem(Bitmap.getBitmapResource("tabitem_default.png"), Bitmap.getBitmapResource("tabitem_selected.png"));
   tab2.setText("Page 2");
   tab3 = new TabItem(Bitmap.getBitmapResource("tabitem_default.png"), Bitmap.getBitmapResource("tabitem_selected.png"));
   tab3.setText("Page 3");
   
   tab1.setFocusListener(this);
   tab2.setFocusListener(this);
   tab3.setFocusListener(this);
   tabcontrol.add(tab1);
   tabcontrol.add(tab2);
   tabcontrol.add(tab3);
   
   add(tabcontrol);
   add(new SeparatorField());
   
   tabArea = displayTab1();
   add(tabArea);
  }

  public void focusChanged(Field field, int eventType) {
   if (tabArea != null) {
    if (eventType == FOCUS_GAINED) {
     if (field == tab1) {
      System.out.println("Switch to Tab 1");
      delete(tabArea);
      tabArea = displayTab1();
      add(tabArea);
     } else if (field == tab2) {
      System.out.println("Switch to Tab 2");
      System.out.println("Switch to Tab 1");
      delete(tabArea);
      tabArea = displayTab2();
      add(tabArea);
     } else if (field == tab3) {
      System.out.println("Switch to Tab 3");
      System.out.println("Switch to Tab 1");
      delete(tabArea);
      tabArea = displayTab3();
      add(tabArea);
     }
    }
   }

  }

  public Manager displayTab1() {
   if (tab1Manager == null) {
    tab1Manager = new VerticalFieldManager();
    tab1Manager.add(new LabelField ("Tab 1 content here."));
    tab1Manager.add(new LabelField ("Tab 1 content here again."));
   }
   return tab1Manager;
  }

  public Manager displayTab2() {
   if (tab2Manager == null) {
    tab2Manager = new VerticalFieldManager();
    tab2Manager.add(new LabelField ("Tab 2 content here."));
    tab2Manager.add(new LabelField ("Tab 2 content here again."));
   }
   return tab2Manager;
  }

  public Manager displayTab3() {
   if (tab3Manager == null) {
    tab3Manager = new VerticalFieldManager();
    tab3Manager.add(new LabelField ("Tab 3 content here."));
    tab3Manager.add(new LabelField ("Tab 3 content here again."));
   }
   return tab3Manager;
  }
 }
}
--------------------------------------------------------------------------------------------------------

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值