首页 > 代码库 > 创建TabHost的两种方式的简单分析

创建TabHost的两种方式的简单分析

最近做了一个TabHost的界面,在做的过程中发现了一些问题,故和大家分享一下。

首先我的界面如下:


目前就我所知,创建TabHost有两种方式,第一种是继承TabActivity类,然后用getTabHost方法来得到一个TabHost的实例,然后就可以给这个TabHost添加Tab了。示例代码如下:

[java] view plaincopy
  1. public class PlotHost extends TabActivity  {  
  2.     @Override  
  3.     protected void onCreate(Bundle savedInstanceState) {  
  4.         // TODO Auto-generated method stub  
  5.         super.onCreate(savedInstanceState);  
  6.           
  7. //      setContentView(R.layout.activity_main);  
  8.           
  9.         setContentView(R.layout.tabhost);  
  10.       
  11.         Resources res=getResources();  
  12.         TabHost tabhost=getTabHost();  
  13.           
  14.         TabSpec dynamicplotSpec;  
  15.         TabSpec staticplotSpec;  
  16.         Intent dynamicplotIntent;  
  17.         Intent staticplotIntent;  
  18.         View dynamicplotView;  
  19.         View staticplotView;  
  20.       
  21.         dynamicplotIntent=new Intent(this,Tab1.class);  
  22.         dynamicplotView=new TabView(this, R.drawable.dynamicploto, R.drawable.dynamicplots, "动态曲线");  
  23.         dynamicplotSpec=tabhost.newTabSpec("DynamicplotTab");  
  24.         dynamicplotSpec.setIndicator(dynamicplotView).setContent(dynamicplotIntent);  
  25.         tabhost.addTab(dynamicplotSpec);  
  26.           
  27.         staticplotSpec=tabhost.newTabSpec("StaticplotTab");  
  28.         staticplotView=new TabView(this, R.drawable.staticploto, R.drawable.staticplots, "历史曲线");  
  29.         staticplotIntent=new Intent(this,Tab2.class);  
  30.         staticplotSpec.setIndicator(staticplotView).setContent(staticplotIntent);  
  31.         tabhost.addTab(staticplotSpec);  
  32.           
  33.         tabhost.setCurrentTab(0);  
  34.           
  35.           
  36.           
  37.     }  
  38.       
  39.     //自定义一个tab选项卡显示样式  
  40.     private  class TabView extends LinearLayout {    
  41.         ImageView imageView ;    
  42.         public TabView(Context c, int drawableSelected, int drawableUnselected,String label) {    
  43.             super(c);    
  44.             this.setOrientation(VERTICAL);  
  45.             imageView = new ImageView(c);    
  46.             StateListDrawable listDrawable = new StateListDrawable();    
  47.             listDrawable.addState(SELECTED_STATE_SET, this.getResources()    
  48.                     .getDrawable(drawableSelected));    
  49.             listDrawable.addState(ENABLED_STATE_SET, this.getResources()    
  50.                     .getDrawable(drawableUnselected));    
  51.             imageView.setImageDrawable(listDrawable);    
  52.             imageView.setBackgroundColor(Color.TRANSPARENT);    
  53.             setGravity(Gravity.CENTER);    
  54.             addView(imageView);    
  55.             TextView tv_label=new TextView(c);  
  56.             tv_label.setText(label);  
  57.             tv_label.setGravity(Gravity.CENTER);  
  58.             addView(tv_label);  
  59.         }  
  60.       
  61.     }     
  62. }  

具体代码我就不用多分析,只需要提一点的就是,用这种方式根本就不用你自定义一个TabHost的组建,getTabHost方法会自动调用系统默认的布局来帮助你进行显示,所以代码里面使用setContentView是多余的。


第二种方式问题就比较多了,其中网上大部分都说直接集成Activity,然后使用findViewbyId找到自定义的TabHost的组件,最后对这个TabHost调用setup方法即可。但是不知道是何原因,也许是我的API版本比较高的原因,使用这种方法始终没有成功,logcat里面报java.lang.RuntimeException异常。最后google后发现,需要改一下方式,即继承ActivityGroup,然后最后setup的时候需要使用setup(this.getLocalActivityManager)即可,代码如下:

[java] view plaincopy
  1. public class PlotHost extends ActivityGroup  {  
  2.     @Override  
  3.     protected void onCreate(Bundle savedInstanceState) {  
  4.         // TODO Auto-generated method stub  
  5.         super.onCreate(savedInstanceState);  
  6.           
  7. //      setContentView(R.layout.activity_main);  
  8.           
  9.         setContentView(R.layout.tabhost);  
  10.       
  11.         Resources res=getResources();  
  12.         TabHost tabhost=(TabHost)findViewById(R.id.tabhost);  
  13.         tabhost.setup(this.getLocalActivityManager());  
  14.           
  15.         TabSpec dynamicplotSpec;  
  16.         TabSpec staticplotSpec;  
  17.         Intent dynamicplotIntent;  
  18.         Intent staticplotIntent;  
  19.         View dynamicplotView;  
  20.         View staticplotView;  
  21.       
  22.         dynamicplotIntent=new Intent(this,Tab1.class);  
  23.         dynamicplotView=new TabView(this, R.drawable.dynamicploto, R.drawable.dynamicplots, "动态曲线");  
  24.         dynamicplotSpec=tabhost.newTabSpec("DynamicplotTab");  
  25.         dynamicplotSpec.setIndicator(dynamicplotView).setContent(dynamicplotIntent);  
  26.         tabhost.addTab(dynamicplotSpec);  
  27.           
  28.         staticplotSpec=tabhost.newTabSpec("StaticplotTab");  
  29.         staticplotView=new TabView(this, R.drawable.staticploto, R.drawable.staticplots, "历史曲线");  
  30.         staticplotIntent=new Intent(this,Tab2.class);  
  31.         staticplotSpec.setIndicator(staticplotView).setContent(staticplotIntent);  
  32.         tabhost.addTab(staticplotSpec);  
  33.           
  34.         tabhost.setCurrentTab(0);  
  35.           
  36.     }  
  37.       
  38.     //自定义一个tab选项卡显示样式  
  39.     private  class TabView extends LinearLayout {    
  40.         ImageView imageView ;    
  41.         public TabView(Context c, int drawableSelected, int drawableUnselected,String label) {    
  42.             super(c);    
  43.             this.setOrientation(VERTICAL);  
  44.             imageView = new ImageView(c);    
  45.             StateListDrawable listDrawable = new StateListDrawable();    
  46.             listDrawable.addState(SELECTED_STATE_SET, this.getResources()    
  47.                     .getDrawable(drawableSelected));    
  48.             listDrawable.addState(ENABLED_STATE_SET, this.getResources()    
  49.                     .getDrawable(drawableUnselected));    
  50.             imageView.setImageDrawable(listDrawable);    
  51.             imageView.setBackgroundColor(Color.TRANSPARENT);    
  52.             setGravity(Gravity.CENTER);    
  53.             addView(imageView);    
  54.             TextView tv_label=new TextView(c);  
  55.             tv_label.setText(label);  
  56.             tv_label.setGravity(Gravity.CENTER);  
  57.             addView(tv_label);  
  58.         }  
  59.       
  60.     }     
  61. }  

其实内容大同小异,至于为什么要这么做,貌似是如果直接调用TabHost的setup方法,不能实例化它的TabWidget和TabContent对象,需要借助于LocalActivityManager自动对二者进行实例化。因为看了一个老兄的博客,setup主要完成的功能便是实例化它的TabWidget和TabContent。如下:

mTabWidget = (TabWidget) findViewById(com.android.internal.R.id.tabs);
        if (mTabWidget == null{
            throw new RuntimeException(
                    "Your TabHost must have a TabWidget whose id attribute is ‘android.R.id.tabs‘");
        }

mTabContent = (FrameLayout) findViewById(com.android.internal.R.id.tabcontent);
        if (mTabContent == null{
            throw new RuntimeException(
                    "Your TabHost must have a FrameLayout whose id attribute is ‘android.R.id.tabcontent‘");
        }

同时,还要补充,使用第二种方法的时候注意修改TabHost在布局当中的ID格式为“@+id/xxx”,其中xxx自定义。其他的步骤在网上一搜一大堆我就不唠叨了。

创建TabHost的两种方式的简单分析