嵌套Tabhost

今天講一下,如何在TabHost中,再放TabHost。

 

先來看一下效果。

 

一層TabHost

 

 

兩層Tabhost (內部TabHots在上面)

 

兩層TabHost (內層TabHots在下面)

 

 

 

下面說一下代碼,一共3個 java類,3個xml佈局文件。

 

看一下主畫面:

main.xml

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <TabHost xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:id="@android:id/tabhost" android:layout_width="fill_parent"  
  4.     android:layout_height="fill_parent"  
  5.     android:background="@drawable/default_bg">  
  6.     <LinearLayout android:orientation="vertical"   
  7.         android:layout_width="fill_parent" android:layout_height="fill_parent">  
  8.         <TabWidget android:id="@android:id/tabs"  
  9.             android:layout_alignParentBottom="true" android:layout_width="fill_parent"  
  10.             android:layout_height="wrap_content"/>  
  11.         <FrameLayout android:id="@android:id/tabcontent"  
  12.             android:layout_weight="1" android:layout_width="fill_parent"  
  13.             android:layout_height="fill_parent" />  
  14.     </LinearLayout>  
  15. </TabHost>  
 

 

就是常規的Tabhost佈局。

 

入口類:

DoubleTabHost.java

  1. package com.yfz;  
  2. import android.app.TabActivity;  
  3. import android.content.Intent;  
  4. import android.os.Bundle;  
  5. import android.widget.TabHost;  
  6. /** 
  7.  * 本類繼承了TabActivity 
  8.  * @author Administrator 
  9.  * 
  10.  */  
  11. public class DoubleTabHost extends TabActivity {  
  12.       
  13.      /* 注意: 
  14.      * 對於TabHost、佈局文件中必須包含 
  15.      * TabHost、TabWidget 、FrameLayout  
  16.      * 如果繼承TabActivity,並且通過getTabHost()方法來獲取TabHost 
  17.      * 那麼三者的ID必須是android.R.id.tabhost、android.R.id.tabs、android.R.id.tabcontent 
  18.      *  
  19.      * 如果繼承Activity,可以通過findViewById來獲取這三個組件,此時ID可自定義 
  20.      */  
  21.       
  22.     /** Called when the activity is first created. */  
  23.     @Override  
  24.     public void onCreate(Bundle savedInstanceState) {  
  25.         super.onCreate(savedInstanceState);  
  26.         setContentView(R.layout.main);  
  27.           
  28.         TabHost mTabHost = getTabHost();  
  29.         mTabHost.addTab(mTabHost.newTabSpec("Twitter").setIndicator(  
  30.                 "Twitter",  
  31.                 getResources().getDrawable(android.R.drawable.arrow_down_float)).setContent(  
  32.                 new Intent(this, SubTab.class)));  
  33.         mTabHost.addTab(mTabHost.newTabSpec("Facebook").setIndicator(  
  34.                 "Facebook",  
  35.                 getResources().getDrawable(android.R.drawable.arrow_down_float)).setContent(  
  36.                 new Intent(this, NormalActivity.class)));  
  37.         mTabHost.setCurrentTab(0);  
  38.     }  
  39. }  
 

 

 

對於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錯誤:

  1. ERROR/AndroidRuntime(8301): Caused by: java.lang.RuntimeException: Your content must have a TabHost whose id attribute is 'android.R.id.tabhost'  
 

 

TabWidget ID 錯誤:

  1. ERROR/AndroidRuntime(8354): Caused by: java.lang.RuntimeException: Your TabHost must have a TabWidget whose id attribute is 'android.R.id.tabs'  
 

 

FrameLayout  ID錯誤:

  1. 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

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <TabHost xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:id="@+id/mytabhost" android:layout_width="fill_parent"  
  4.     android:layout_height="fill_parent"  
  5.     android:background="@drawable/default_bg">  
  6.     <LinearLayout android:orientation="vertical"   
  7.         android:layout_width="fill_parent" android:layout_height="fill_parent">  
  8.         <!-- 注意FrameLayout/TabWidget標籤的位置-->  
  9.         <FrameLayout android:id="@android:id/tabcontent"  
  10.             android:layout_weight="1" android:layout_width="fill_parent"  
  11.             android:layout_height="fill_parent" >  
  12.                 <TextView  
  13.                     android:id="@+id/widget59"  
  14.                     android:layout_width="wrap_content"  
  15.                     android:layout_height="wrap_content"  
  16.                     android:text="你在想什麼?"  
  17.                     android:layout_alignParentTop="true"  
  18.                     android:layout_centerHorizontal="true"  
  19.                     >  
  20.                     </TextView>  
  21.                     <TextView  
  22.                     android:id="@+id/widget60"  
  23.                     android:layout_width="wrap_content"  
  24.                     android:layout_height="wrap_content"  
  25.                     android:text="我在想Android"  
  26.                     android:layout_alignParentTop="true"  
  27.                     android:layout_alignParentRight="true"  
  28.                     >  
  29.                     </TextView>  
  30.         </FrameLayout>  
  31.         <TabWidget android:id="@android:id/tabs"  
  32.             android:layout_alignParentBottom="true" android:layout_width="fill_parent"  
  33.             android:layout_height="wrap_content"/>  
  34.     </LinearLayout>  
  35. </TabHost>  
 

 

子TabHost頁面加載類:

SubTab.java

  1. package com.yfz;  
  2. import android.app.Activity;  
  3. import android.os.Bundle;  
  4. import android.widget.TabHost;  
  5. import android.widget.TabWidget;  
  6. import android.widget.TextView;  
  7. /** 
  8.  *  
  9.  * @author Administrator 
  10.  * 
  11.  */  
  12. public class SubTab extends Activity {  
  13.       
  14.     @Override  
  15.     public void onCreate(Bundle savedInstanceState) {  
  16.         super.onCreate(savedInstanceState);  
  17.         setContentView(R.layout.subtab);  
  18.           
  19.         //以下三句代碼,注意順序  
  20.         TabHost mTabHost = (TabHost)findViewById(R.id.mytabhost);  
  21.         mTabHost.setup();  
  22.         TabWidget tabWidget = mTabHost.getTabWidget();  
  23.           
  24.         mTabHost.addTab(mTabHost.newTabSpec("蘇州").setIndicator(  
  25.                 "蘇州").setContent(R.id.widget59));  
  26.         mTabHost.addTab(mTabHost.newTabSpec("上海").setIndicator(  
  27.                 "上海").setContent(R.id.widget60));  
  28.         mTabHost.addTab(mTabHost.newTabSpec("天津").setIndicator(  
  29.                 "天津").setContent(R.id.widget60));  
  30.         mTabHost.addTab(mTabHost.newTabSpec("北京").setIndicator(  
  31.                 "北京").setContent(R.id.widget60));  
  32.         mTabHost.setCurrentTab(0);  
  33.           
  34.         int height =30;   
  35. //      int width =45;   
  36.               
  37.         for (int i =0; i < tabWidget.getChildCount(); i++) {  
  38.               
  39.             /**設置高度、寬度,由於寬度設置爲fill_parent,在此對它沒效果 */   
  40.             tabWidget.getChildAt(i).getLayoutParams().height = height;   
  41. //            tabWidget.getChildAt(i).getLayoutParams().width = width;   
  42.             /**設置tab中標題文字的顏色,不然默認爲黑色 */   
  43.              final TextView tv = (TextView) tabWidget.getChildAt(i).findViewById(android.R.id.title);   
  44.              tv.setTextColor(this.getResources().getColorStateList(android.R.color.white));   
  45.         }  
  46.     }  
  47. }  
 

 

如果加載TabHost畫面的繼承自Activity,可以通過findViewById來獲取這三個組件,此時ID可自定義。

需要注意的是,此時必須調用setup方法來加載TabHost。

 

對了,不要忘了在AndroidManifest.xml定義Activity~~呵呵!

 

要點就這麼多~ 就這樣了。

 

 

 

源碼我會上傳,地址稍後給出。

 

源程序下載地址:   http://download.csdn.net/source/3037680  

 

 

 


 

BUG對應。  感謝simayilong 和 gz116 提出這兩個典型問題。

 

問題一:無法在子tabhost中打開Activity。

  1. 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 不能顯示

 

  1. 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()) 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章