今天講一下,如何在TabHost中,再放TabHost。
先來看一下效果。
一層TabHost
兩層Tabhost (內部TabHots在上面),如上右圖所示。
兩層TabHost (內層TabHots在下面)
下面說一下代碼,一共3個 java類,3個xml布局檔案。
看一下主畫面:
main.xml
<?xml version="1.0" encoding="utf-8"?> <TabHost xmlns:android="http://schemas.android.com/apk/res/android" android:id="@android:id/tabhost" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@drawable/default_bg"> <LinearLayout android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <TabWidget android:id="@android:id/tabs" android:layout_alignParentBottom="true" android:layout_width="fill_parent" android:layout_height="wrap_content"/> <FrameLayout android:id="@android:id/tabcontent" android:layout_weight="1" android:layout_width="fill_parent" android:layout_height="fill_parent" /> </LinearLayout> </TabHost>
就是常規的Tabhost布局。
入口類:
DoubleTabHost.java
package com.yfz;import android.app.TabActivity;import android.content.Intent;import android.os.Bundle;import android.widget.TabHost;/** * 本類繼承了TabActivity * @author Administrator * */public class DoubleTabHost extends TabActivity { /* 注意: * 對於TabHost、布局檔案中必須包含 * TabHost、TabWidget 、FrameLayout * 如果繼承TabActivity,並且通過getTabHost()方法來擷取TabHost * 那麼三者的ID必須是android.R.id.tabhost、android.R.id.tabs、android.R.id.tabcontent * * 如果繼承Activity,可以通過findViewById來擷取這三個組件,此時ID可自訂 */ /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); TabHost mTabHost = getTabHost();mTabHost.addTab(mTabHost.newTabSpec("Twitter").setIndicator("Twitter",getResources().getDrawable(android.R.drawable.arrow_down_float)).setContent(new Intent(this, SubTab.class)));mTabHost.addTab(mTabHost.newTabSpec("Facebook").setIndicator("Facebook",getResources().getDrawable(android.R.drawable.arrow_down_float)).setContent(new Intent(this, NormalActivity.class)));mTabHost.setCurrentTab(0); }}
對於TabHost、布局檔案中必須包含TabHost、TabWidget 、FrameLayout .缺一不可
如果載入該TabHost畫面的類繼承TabActivity,並且想通過getTabHost()方法來擷取TabHost,getTabWidget()方法擷取TabWidget,
那麼TabHost、TabWidget 、FrameLayout 三者的ID必須是android.R.id.tabhost、android.R.id.tabs、android.R.id.tabcontent
否則會報運行時異常,錯誤如下:
TabHost ID錯誤:
ERROR/AndroidRuntime(8301): Caused by: java.lang.RuntimeException: Your content must have a TabHost whose id attribute is 'android.R.id.tabhost'
TabWidget ID 錯誤:
ERROR/AndroidRuntime(8354): Caused by: java.lang.RuntimeException: Your TabHost must have a TabWidget whose id attribute is 'android.R.id.tabs'
FrameLayout ID錯誤:
ERROR/AndroidRuntime(8404): Caused by: java.lang.RuntimeException: Your TabHost must have a FrameLayout whose id attribute is 'android.R.id.tabcontent'
子TabHost頁面:
subtab.xml
<?xml version="1.0" encoding="utf-8"?><TabHost xmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/mytabhost" android:layout_width="fill_parent"android:layout_height="fill_parent"android:background="@drawable/default_bg"><LinearLayout android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"><!-- 注意FrameLayout/TabWidget標籤的位置--><FrameLayout android:id="@android:id/tabcontent"android:layout_weight="1" android:layout_width="fill_parent"android:layout_height="fill_parent" ><TextViewandroid:id="@+id/widget59"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="你在想什嗎?"android:layout_alignParentTop="true"android:layout_centerHorizontal="true"></TextView><TextViewandroid:id="@+id/widget60"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="我在想Android"android:layout_alignParentTop="true"android:layout_alignParentRight="true"></TextView></FrameLayout><TabWidget android:id="@android:id/tabs"android:layout_alignParentBottom="true" android:layout_width="fill_parent"android:layout_height="wrap_content"/></LinearLayout></TabHost>
子TabHost頁面載入類:
SubTab.java
package com.yfz;import android.app.Activity;import android.os.Bundle;import android.widget.TabHost;import android.widget.TabWidget;import android.widget.TextView;/** * * @author Administrator * */public class SubTab extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.subtab); //以下三句代碼,注意順序TabHost mTabHost = (TabHost)findViewById(R.id.mytabhost);mTabHost.setup();TabWidget tabWidget = mTabHost.getTabWidget();mTabHost.addTab(mTabHost.newTabSpec("蘇州").setIndicator("蘇州").setContent(R.id.widget59));mTabHost.addTab(mTabHost.newTabSpec("上海").setIndicator("上海").setContent(R.id.widget60));mTabHost.addTab(mTabHost.newTabSpec("天津").setIndicator("天津").setContent(R.id.widget60));mTabHost.addTab(mTabHost.newTabSpec("北京").setIndicator("北京").setContent(R.id.widget60));mTabHost.setCurrentTab(0);int height =30; //int width =45; for (int i =0; i < tabWidget.getChildCount(); i++) { /**設定高度、寬度,由於寬度設定為fill_parent,在此對它沒效果 */ tabWidget.getChildAt(i).getLayoutParams().height = height; // tabWidget.getChildAt(i).getLayoutParams().width = width; /**設定tab中標題文字的顏色,不然預設為黑色 */ final TextView tv = (TextView) tabWidget.getChildAt(i).findViewById(android.R.id.title); tv.setTextColor(this.getResources().getColorStateList(android.R.color.white)); } }}
如果載入TabHost畫面的繼承自Activity,可以通過findViewById來擷取這三個組件,此時ID可自訂。
需要注意的是,此時必須調用setup方法來載入TabHost。
對了,不要忘了在AndroidManifest.xml定義Activity~~呵呵!
要點就這麼多~ 就這樣了。
來源程式: http://download.csdn.net/source/3037680
BUG對應。 感謝simayilong 和 gz116 提出這兩個典型問題。
問題一:無法在子tabhost中開啟Activity。
java.lang.IllegalStateException: Did you forget to call 'public void setup(LocalActivityManager activityGroup)'?
解決辦法1:
1. 將初始化tabHost的那個類(此例中為SubTab類),繼承ActivityGroup,而不是Activity
2. tabhost.setup() 改為 tabHost.setup(this.getLocalActivityManager());
具體參考:
http://stackoverflow.com/questions/3272500/android-exception-did-you-forget-to-call-public-void-setup-localactivitymanage
http://hi.baidu.com/ljlkings/blog/item/47f1afdbdcd27de638012f76.html
解決辦法2:
也可以將SubTab類改繼承TabActivity,然後布局檔案中Tabhost的id改為@android:id/tabhost.
因為TabActivity也是繼承自ActivitGroup的。
以上兩種方法都可以。
問題二: TabHost 嵌套後,Dialog 不能顯示
android.view.WindowManager$BadTokenException: Unable to add window -- token android.app.LocalActivityManager$LocalActivityRecord@43e57e20 is not valid; is your activity running?
解決辦法:
AlertDialog.Builder(xxx.this) => AlertDialog.Builder(xxx.this.getParent())
參考資料:
嵌套TabHost (TabHost中放TabHost,類似二級目錄、二級樹)
【Android進階】嵌套TabHost (TabHost中放TabHost,類似二級目錄、二級樹)