news 2026/9/2 19:26:00

TabActivity、TabHost、NavController

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
TabActivity、TabHost、NavController

1.TabActivity 继承自Activity,其内部定义好了TabHost,可以通过getTabHost()获取TabHost。

TabHost 包含了两种子元素:一些可以自由选择的Tab,及 与这些tab对应的内容tabContent,在layout的<TabHost>下它们分别对应 TabWidget (用于展示标签页, id固定为tabs )和 FrameLayout(用于展示隶属于各个标签的具体布局, id固定为tabcontent)。

Tabhost默认的布局文件:

<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" >
<LinearLayout
android:orientation="vertical"
android:gravity="bottom"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >


<TabWidget
android:id="@android:id/tabs"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />


<FrameLayout
android:id="@android:id/tabcontent"
android:layout_width="fill_parent"
android:layout_height="200dip" >
</FrameLayout>


</LinearLayout>
</TabHost>

2.最简单的TabActivity示例,不用设置setContentView(R.layout.main); ,不依靠布局文件:

public class ILoveConactActivity extends TabActivity implements TabHost.TabContentFactory,OnTabChangeListener
{
public void onCreate(Bundle icicle)
{
super.onCreate(icicle);

//取得TabHost对象
TabHost tabHost=this.getTabHost();
tabHost.setOnTabChangedListener(this);

for(int i=0;i<4;i++)
{

String tabItemTitle="tab"+i;
String tabItemTag=""+i;


TabSpec tabSpec=tabHost.newTabSpec(tabItemTag);
tabSpec.setIndicator(tabItemTitle);//或者setIndicator(CharSequence label, Drawable icon) ,setIndicator(View view)

/*

或者tabSpec.setContent(R.id.viewId);//R.id.viewId是在布局文件中的view的id。,setIndicator(View view),

setContent(TabContentFactory contentFactory)时会动态确定内容。

setContent(Intent intent) Specify an intent to use to launch an activity as the tab content.

*/

tabSpec.setContent(this);



tabHost.addTab(tabSpec);
}

tabHost.setCurrentTab(1);//或者setCurrentTabByTag(String tag)

//加上下面这4行代码,使TabWidget到底部:

TabWidget tabWidget = this.getTabWidget(); //或者tabHost.getTabWidget();

LinearLayout layout= (LinearLayout) tabHost.getChildAt(0);

layout.removeViewAt(0);

layout.addView(tabWidget);//把tabWidget 从第一个位置移除,再添加到下面来。
}

@Override
public void onTabChanged(String tabId)
{
// TODO Auto-generated method stub
}

@Override
public View createTabContent(String tag)
{
TextView view=new TextView(this);
view.setText("tab content "+tag);
return view;//不能返回null,否则会报错。
}

}

intent必须是一个关联Activity的intent。

android中文api (59) —— TabHost.TabSpec - 农民伯伯 - 博客园

3.对TabWidget的理解:

(1)TabWidget 为 horizontal 的 LinearLayout
(2)且 其包含的标签又是一个RelativeLayout
(3) 每个标签RelativeLayout 里面包含2个View:TextView和ImageView

推算出其布局为:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<RelativeLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<ImageView />
<TextView />
</RelativeLayout>
<RelativeLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<ImageView />
<TextView />
</RelativeLayout>
<RelativeLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<ImageView />
<TextView />
</RelativeLayout>
<RelativeLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<ImageView />
<TextView />
</RelativeLayout>
</LinearLayout>

4.基于默认的Tabhost布局文件,自定义布局文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">


<!-- TabHost必须包含一个 TabWidget和一个FrameLayout-->
<TabHost android:id="@+id/tabhost"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>


<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">


<!-- TabWidget的id属性必须为 @android:id/tabs-->
<TabWidget android:id="@android:id/tabs"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
</TabWidget>


<!-- FrameLayout的id属性必须为 @android:id/tabcontent-->
<FrameLayout android:id="@android:id/tabcontent"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView android:id="@+id/view1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
<TextView android:id="@+id/view2"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
<TextView android:id="@+id/view3"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
</FrameLayout>

</LinearLayout>
</TabHost>
</LinearLayout>
5.TabHost中的子Activity虽然是用Intent参数来启动,但实际上并没有去启动一个全新的Activity。维护了几个子View

6.ActivityGroup的问题:

它是用来做Tab切换用的,不是用做栈导航的;

在一个ActivityGroup中连续开启同一个Activity,第2个及之后和第1个在创建菜单的函数调用顺序上不同;

在一个ActivityGroup中连续开启同一个Activity非同一个Activity,后面的创建菜单的函数不再调用了...

另外也没有StartActivityForResult函数。
ActivityGroup中可以指定界面中的各个部分内容来自不同的Activity,这时这些Actvitiy只作为内容管理单元。

NavHostFragment

NavHostFragment 是 Android Jetpack Navigation 组件里的一个特殊 Fragment,用来当作导航的宿主容器,负责展示当前应该显示的那个页面(也就是导航图里的“目的地”)。‌‌

🧩 核心作用

  • 容器角色‌:它是 Activity 和各个 Fragment 之间的“展示窗口”,导航图里定义的所有页面都要通过它来显示。
  • 自动管理‌:它会自动帮你处理页面之间的切换、返回栈管理以及转场动画。
  • 绑定关系‌:每个 NavHostFragment 都配有一个 ‌NavController‌,NavController 是实际执行导航操作的核心对象。‌‌
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/2 19:25:13

从Fableish失败案例看AI心智理论与工程化实践避坑指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/2 19:19:35

Claude隐形文本水印技术解析:原理、检测与工程实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/2 19:18:52

游戏抽卡资源规划:从零实现满破UR双武奥米加兽的实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/2 19:17:51

从Reactor到FastH3:实时AI视频流与无限直播的工程密码

最近在逛社区的时候&#xff0c;我注意到一个项目标题&#xff1a;“Reactor联合HaoAI推出FastH3无限直播流”。这三个词放在一起&#xff0c;确实很抓人眼球&#xff1a;Reactor是Stable Diffusion生态里比较出名的实时人脸处理插件&#xff0c;HaoAI听起来像一个提供模型或算…

作者头像 李华
网站建设 2026/9/2 19:10:57

混合不确定性+鲁棒协同优化:风光储微电网容量规划实战

风光储微电网的容量规划&#xff0c;听起来是个很“传统”的优化问题——建多少风机、装多少光伏、配多少储能&#xff0c;算清楚就行。但真正做过这个方向的人都知道&#xff0c;难点从来不在数学公式有多复杂&#xff0c;而在于&#xff1a;你算出来的“最优方案”&#xff0…

作者头像 李华
网站建设 2026/9/2 19:09:31

微服务是被增长逼出来的:Uber架构演进与工程实践启示

很多团队在规划微服务时&#xff0c;都会先画出一张漂亮的分层架构图&#xff1a;API 网关、服务注册中心、配置中心、监控链路、分布式链路追踪&#xff0c;一应俱全。但 Uber 前 CTO 在回顾这段工程历史时&#xff0c;却说出了一个反直觉的结论&#xff1a;微服务架构不是被设…

作者头像 李华