天水郡人

胸有猛虎,细嗅蔷薇

  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 :: 管理 ::

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

先来看一下效果。

一层TabHost

两层Tabhost (内部TabHots在上面)

两层TabHost (内层TabHots在下面)

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

看一下主画面:

main.xml

01.<?xml version="1.0" encoding="utf-8"?>  
02.<TabHost xmlns:android="http://schemas.android.com/apk/res/android"
03. android:id
="@android:id/tabhost" android:layout_width="fill_parent"
04. android:layout_height
="fill_parent"
05. android:background
="@drawable/default_bg">
06. <LinearLayout android:orientation="vertical"
07. android:layout_width
="fill_parent" android:layout_height="fill_parent">
08. <TabWidget android:id="@android:id/tabs"
09. 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

01.package com.yfz;  
02.import android.app.TabActivity;
03.import android.content.Intent;
04.import android.os.Bundle;
05.import android.widget.TabHost;
06./**
07. * 本类继承了TabActivity
08. *
@author Administrator
09. *
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错误:

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

01.<?xml version="1.0" encoding="utf-8"?>  
02.<TabHost xmlns:android="http://schemas.android.com/apk/res/android"
03. android:id="@+id/mytabhost" android:layout_width="fill_parent"
04. android:layout_height="fill_parent"
05. android:background="@drawable/default_bg">
06. <LinearLayout android:orientation="vertical"
07. android:layout_width="fill_parent" android:layout_height="fill_parent">
08. <!-- 注意FrameLayout/TabWidget标签的位置-->
09. <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

01.package com.yfz;  
02.import android.app.Activity;
03.import android.os.Bundle;
04.import android.widget.TabHost;
05.import android.widget.TabWidget;
06.import android.widget.TextView;
07./**
08. *
09. *
@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对应。  感谢simayilonggz116 提出这两个典型问题。

问题一:无法在子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 不能显示

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

本文引用至:

http://blog.csdn.net/feng88724/article/details/6203358

posted on 2012-03-16 10:05  xiongweizhuang  阅读(3804)  评论(0)    收藏  举报