最近做了一个TabHost的界面,在做的过程中发现了一些问题,故和大家分享一下。
首先我的界面如下:
目前就我所知,创建TabHost有两种方式,第一种是继承TabActivity类,然后用getTabHost方法来得到一个TabHost的实例,然后就可以给这个TabHost添加Tab了。示例代码如下:
public class PlotHost extends TabActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
// setContentView(R.layout.activity_main);
setContentView(R.layout.tabhost);
Resources res=getResources();
TabHost tabhost=getTabHost();
TabSpec dynamicplotSpec;
TabSpec staticplotSpec;
Intent dynamicplotIntent;
Intent staticplotIntent;
View dynamicplotView;
View staticplotView;
dynamicplotIntent=new Intent(this,Tab1.class);
dynamicplotView=new TabView(this, R.drawable.dynamicploto, R.drawable.dynamicplots, "动态曲线");
dynamicplotSpec=tabhost.newTabSpec("DynamicplotTab");
dynamicplotSpec.setIndicator(dynamicplotView).setContent(dynamicplotIntent);
tabhost.addTab(dynamicplotSpec);
staticplotSpec=tabhost.newTabSpec("StaticplotTab");
staticplotView=new TabView(this, R.drawable.staticploto, R.drawable.staticplots, "历史曲线");
staticplotIntent=new Intent(this,Tab2.class);
staticplotSpec.setIndicator(staticplotView).setContent(staticplotIntent);
tabhost.addTab(staticplotSpec);
tabhost.setCurrentTab(0);
}
//自定义一个tab选项卡显示样式
private class TabView extends LinearLayout {
ImageView imageView ;
public TabView(Context c, int drawableSelected, int drawableUnselected,String label) {
super(c);
this.setOrientation(VERTICAL);
imageView = new ImageView(c);
StateListDrawable listDrawable = new StateListDrawable();
listDrawable.addState(SELECTED_STATE_SET, this.getResources()
.getDrawable(drawableSelected));
listDrawable.addState(ENABLED_STATE_SET, this.getResources()
.getDrawable(drawableUnselected));
imageView.setImageDrawable(listDrawable);
imageView.setBackgroundColor(Color.TRANSPARENT);
setGravity(Gravity.CENTER);
addView(imageView);
TextView tv_label=new TextView(c);
tv_label.setText(label);
tv_label.setGravity(Gravity.CENTER);
addView(tv_label);
}
}
}
具体代码我就不用多分析,只需要提一点的就是,用这种方式根本就不用你自定义一个TabHost的组建,getTabHost方法会自动调用系统默认的布局来帮助你进行显示,所以代码里面使用setContentView是多余的。
第二种方式问题就比较多了,其中网上大部分都说直接集成Activity,然后使用findViewbyId找到自定义的TabHost的组件,最后对这个TabHost调用setup方法即可。但是不知道是何原因,也许是我的API版本比较高的原因,使用这种方法始终没有成功,logcat里面报java.lang.RuntimeException异常。最后google后发现,需要改一下方式,即继承ActivityGroup,然后最后setup的时候需要使用setup(this.getLocalActivityManager)即可,代码如下:
public class PlotHost extends ActivityGroup {
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
// setContentView(R.layout.activity_main);
setContentView(R.layout.tabhost);
Resources res=getResources();
TabHost tabhost=(TabHost)findViewById(R.id.tabhost);
tabhost.setup(this.getLocalActivityManager());
TabSpec dynamicplotSpec;
TabSpec staticplotSpec;
Intent dynamicplotIntent;
Intent staticplotIntent;
View dynamicplotView;
View staticplotView;
dynamicplotIntent=new Intent(this,Tab1.class);
dynamicplotView=new TabView(this, R.drawable.dynamicploto, R.drawable.dynamicplots, "动态曲线");
dynamicplotSpec=tabhost.newTabSpec("DynamicplotTab");
dynamicplotSpec.setIndicator(dynamicplotView).setContent(dynamicplotIntent);
tabhost.addTab(dynamicplotSpec);
staticplotSpec=tabhost.newTabSpec("StaticplotTab");
staticplotView=new TabView(this, R.drawable.staticploto, R.drawable.staticplots, "历史曲线");
staticplotIntent=new Intent(this,Tab2.class);
staticplotSpec.setIndicator(staticplotView).setContent(staticplotIntent);
tabhost.addTab(staticplotSpec);
tabhost.setCurrentTab(0);
}
//自定义一个tab选项卡显示样式
private class TabView extends LinearLayout {
ImageView imageView ;
public TabView(Context c, int drawableSelected, int drawableUnselected,String label) {
super(c);
this.setOrientation(VERTICAL);
imageView = new ImageView(c);
StateListDrawable listDrawable = new StateListDrawable();
listDrawable.addState(SELECTED_STATE_SET, this.getResources()
.getDrawable(drawableSelected));
listDrawable.addState(ENABLED_STATE_SET, this.getResources()
.getDrawable(drawableUnselected));
imageView.setImageDrawable(listDrawable);
imageView.setBackgroundColor(Color.TRANSPARENT);
setGravity(Gravity.CENTER);
addView(imageView);
TextView tv_label=new TextView(c);
tv_label.setText(label);
tv_label.setGravity(Gravity.CENTER);
addView(tv_label);
}
}
}
其实内容大同小异,至于为什么要这么做,貌似是如果直接调用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自定义。其他的步骤在网上一搜一大堆我就不唠叨了。