Android中TabHost嵌套TabHost

在嵌套TabHost时,先后遇到了以下情况:

问题1:内部TabHos无显示,只显示了其中的一个Activity;

解决:按下文比对主子TabHos的布局文件和java文件并修改;

问题2:如上所做后,遇到下文所提的问题一;

解决:按其方案可解决;

问题3:如上所做后,发现点击主/子TabHost中ListView的item均报异常,如下文所提的问题二;

解决:按其方案可解决。

下文原址:http://blog.csdn.net/feng88724/article/details/6203358

-----------------------------------------------------------------------------------------------------------

 今天讲一下,如何在TabHost中,再放TabHost,先来看一下效果,一层TabHost:

Android中TabHost嵌套TabHost

两层Tabhost (内部TabHots在上面)

Android中TabHost嵌套TabHost

两层TabHost (内层TabHots在下面)

Android中TabHost嵌套TabHost

下面说一下代码,一共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>

入口类,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错误:

  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:

<?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" >  

                <TextView  

                    android:id="@+id/widget59"  

                    android:layout_width="wrap_content"  

                    android:layout_height="wrap_content"  

                    android:text="你在想什么?"  

                    android:layout_alignParentTop="true"  

                    android:layout_centerHorizontal="true"  

                    >  

                    </TextView>  

                    <TextView  

                    android: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~~呵呵!

要点就这么多~ 就这样了。

 

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

 

 

 

你可能感兴趣的:(android)