您的位置:首页 > 移动开发 > Android开发

嵌套TabHost (TabHost中放TabHost,类似二级目录、二级树)

2012-03-16 17:02 375 查看
 

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

 

先来看一下效果。

 

一层TabHost

 





 

两层Tabhost (内部TabHots在上面)





 

两层TabHost (内层TabHots在下面)

 





 

 

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

 

看一下主画面:

main.xml

源码copy to clipboard打印

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

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

源码copy to clipboard打印

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);   
    }   
}  

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错误:

源码copy to clipboard打印

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

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

 

TabWidget ID 错误:

源码copy to clipboard打印

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

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

 

FrameLayout  ID错误:

源码copy to clipboard打印

ERROR/AndroidRuntime(8404): Caused by: java.lang.RuntimeException: Your TabHost must have a FrameLayout whose id attribute is 'android.R.id.tabcontent'  

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

源码copy to clipboard打印

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

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

源码copy to clipboard打印

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));    
        }   
    }   
}  

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。

源码copy to clipboard打印

java.lang.IllegalStateException: Did you forget to call 'public void setup(LocalActivityManager activityGroup)'?  

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 不能显示

 

源码copy to clipboard打印

android.view.WindowManager$BadTokenException: Unable to add window -- token android.app.LocalActivityManager$LocalActivityRecord@43e57e20 is not valid; is your activity running?  

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

标签: <无>
补充话题说明»
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐