【Android进阶】嵌套TabHost (TabHost中放TabHost,类似二级目录、二级树)

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

 

先来看一下效果。

 

一层TabHost

 

 

两层Tabhost (内部TabHots在上面)

 

两层TabHost (内层TabHots在下面)

 

 

 

下面说一下代码,一共3个 java类,3个xml布局文件。

 

看一下主画面:

main.xml

 

 

就是常规的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

 

 

子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()) 

你可能感兴趣的:(【Android进阶】)