最近做了一個TabHost的介面,在做的過程中發現了一些問題,故和大家分享一下。
首先我的介面如下:
目前就我所知,建立TabHost有兩種方式,第一種是繼承TabActivity類,然後用getTabHost方法來得到一個TabHost的執行個體,然後就可以給這個TabHost添加Tab了。範例程式碼如下:
public class PlotHost extends TabActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {// TODO Auto-generated method stubsuper.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 {@Overrideprotected void onCreate(Bundle savedInstanceState) {// TODO Auto-generated method stubsuper.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自訂。其他的步驟在網上一搜一大堆我就不嘮叨了。