常用的TabHost实现方式有两种:一种是继承TabActivity,另一种是不继承。现就两种方式实现一下:
1.不继承
TabActivity
activity_main.xml文件
-
<LinearLayout xmlns:android=""
-
xmlns:tools=""
-
android:layout_width="match_parent"
-
android:layout_height="match_parent"
-
android:orientation="vertical"
-
tools:context="com.example.tabhostpractice.MainActivity">
-
-
<TabHost
-
android:id="@+id/tabhost"
-
android:layout_width="match_parent"
-
android:layout_height="match_parent">
-
-
<TabWidget
-
android:id="@android:id/tabs"
-
android:layout_width="match_parent"
-
android:layout_height="wrap_content"
-
></TabWidget>
-
<FrameLayout
-
android:id="@android:id/tabcontent"
-
android:layout_width="match_parent"
-
android:layout_height="match_parent"
-
></FrameLayout>
-
</TabHost>
-
</LinearLayout>
在这个TabHost中有两个标签,对应的两个标签页用两个xml文件来实现
layout11.xml
-
<?xml version="1.0" encoding="utf-8"?>
-
<LinearLayout xmlns:android=""
-
android:layout_width="match_parent"
-
android:layout_height="match_parent"
-
android:id="@+id/layout1"
-
android:gravity="center"
-
android:orientation="vertical">
-
-
<TextView
-
android:layout_width="wrap_content"
-
android:layout_height="wrap_content"
-
android:textSize="30sp"
-
android:text="this is first" />
-
</LinearLayout>
layout22.xml
-
<?xml version="1.0" encoding="utf-8"?>
-
<LinearLayout xmlns:android=""
-
android:layout_width="match_parent"
-
android:layout_height="match_parent"
-
android:id="@+id/layout2"
-
android:gravity="center"
-
android:orientation="vertical">
-
-
<TextView
-
android:layout_width="wrap_content"
-
android:layout_height="wrap_content"
-
android:textSize="30sp"
-
android:text="this is two" />
-
</LinearLayout>
主文件
-
public class MainActivity extends AppCompatActivity {
-
TabHost mTabhost;
-
@Override
-
protected void onCreate(Bundle savedInstanceState) {
-
super.onCreate(savedInstanceState);
-
setContentView(R.layout.activity_main);
-
-
mTabhost = (TabHost) findViewById(R.id.tabhost);
-
mTabhost.setup();
-
-
LayoutInflater inflater = LayoutInflater.from(getApplicationContext());
-
inflater.inflate(R.layout.layout11,mTabhost.getTabContentView());
-
inflater.inflate(R.layout.layout22,mTabhost.getTabContentView());
-
-
-
TabHost.TabSpec spec1 = mTabhost.newTabSpec("11");
-
spec1.setIndicator("first");
-
spec1.setContent(R.id.layout1);
-
-
TabHost.TabSpec spec2 = mTabhost.newTabSpec("22");
-
spec2.setIndicator("two");
-
spec2.setContent(R.id.layout2);
-
-
mTabhost.addTab(spec1);
-
mTabhost.addTab(spec2);
-
}
-
}
其中11和22是tabId,在标签页切换时,调用的
onTabChanged(String tabId)中会用到。若想为每个标签添加图片,可用spec1.setIndicator()来实现;若想让标签实现特殊的布局,可另建一个xml文件来实现布局,详细见下面的另一个例子。
另外,也可以直接在TabHost控件所在的xml文件中直接设置tab的布局内容,这样在主文件中不用再动态加载xml文件了,一些简易的布局时,可以这样实现。
-
<?xml version="1.0" encoding="utf-8"?>
-
<LinearLayout xmlns:android=""
-
xmlns:tools=""
-
android:layout_width="match_parent"
-
android:layout_height="match_parent"
-
android:orientation="vertical"
-
tools:context="com.example.tabhostpractice.MainActivity">
-
-
<TabHost
-
android:id="@+id/tabhost"
-
android:layout_width="match_parent"
-
android:layout_height="match_parent">
-
-
<LinearLayout
-
android:layout_width="match_parent"
-
android:layout_height="match_parent"
-
android:orientation="vertical">
-
-
<TabWidget
-
android:id="@android:id/tabs"
-
android:layout_width="match_parent"
-
android:layout_height="wrap_content"></TabWidget>
-
-
<FrameLayout
-
android:id="@android:id/tabcontent"
-
android:layout_width="match_parent"
-
android:layout_height="match_parent">
-
-
<!-- 第一个tab的布局 -->
-
<LinearLayout
-
android:id="@+id/tab1"
-
android:layout_width="match_parent"
-
android:layout_height="match_parent">
-
-
<TextView
-
android:id="@+id/textView1"
-
android:layout_width="wrap_content"
-
android:layout_height="wrap_content"
-
android:text="this is first" />
-
-
</LinearLayout>
-
-
<!-- 第二个tab的布局 -->
-
<LinearLayout
-
android:id="@+id/tab2"
-
android:layout_width="match_parent"
-
android:layout_height="match_parent">
-
-
<TextView
-
android:id="@+id/textView2"
-
android:layout_width="wrap_content"
-
android:layout_height="wrap_content"
-
android:text="this is two" />
-
-
</LinearLayout>
-
-
<!-- 第三个tab的布局 -->
-
<LinearLayout
-
android:id="@+id/tab0"
-
android:layout_width="match_parent"
-
android:layout_height="match_parent">
-
-
<TextView
-
android:id="@+id/textView0"
-
android:layout_width="wrap_content"
-
android:layout_height="wrap_content"
-
android:text="this is three" />
-
</LinearLayout>
-
-
</FrameLayout>
-
</LinearLayout>
-
</TabHost>
-
</LinearLayout>
这种情况,在预览区就可以看到真正运行时在第一个tab时的样子,而tab的标题为每个布局的id,三个tab标题依次为:tab1,tab2,tab0。
-
public class MainActivity extends AppCompatActivity {
-
TabHost mTabhost;
-
@Override
-
protected void onCreate(Bundle savedInstanceState) {
-
super.onCreate(savedInstanceState);
-
setContentView(R.layout.activity_main);
-
-
mTabhost = (TabHost)findViewById(R.id.tabhost);
-
mTabhost.setup();
-
-
TabHost.TabSpec spec1 = mTabhost.newTabSpec("11");
-
spec1.setIndicator("first");
-
spec1.setContent(R.id.tab1);
-
-
TabHost.TabSpec spec2 = mTabhost.newTabSpec("22");
-
spec2.setIndicator("two");
-
spec2.setContent(R.id.tab2);
-
-
TabHost.TabSpec spec3 = mTabhost.newTabSpec("00");
-
spec3.setIndicator("three");
-
spec3.setContent(R.id.tab0);
-
-
-
mTabhost.addTab(spec1);
-
mTabhost.addTab(spec2);
-
mTabhost.addTab(spec3);
-
}
-
}
2.继承自TabActivity
在此不用在xml文件中使用TabHost控件了,而是使用android内部定义好的tab_content.xml ,也就是在代码中使用getTabHost(),其后台源码如下:
-
public TabHost getTabHost() {
-
ensureTabHost();
-
return mTabHost;
-
}
-
-
private void ensureTabHost() {
-
if (mTabHost == null) {
-
this.setContentView(com.android.internal.R.layout.tab_content);
-
}
-
}
而其内部的tab_content.xml文件为:
-
<TabHost
-
xmlns:android=""
-
android:id="@android:id/tabhost"
-
android:layout_width="match_parent"
-
android:layout_height="match_parent">
-
-
<LinearLayout
-
android:orientation="vertical"
-
android:layout_width="match_parent"
-
android:layout_height="match_parent">
-
-
<TabWidget
-
android:id="@android:id/tabs"
-
android:orientation="horizontal"
-
android:layout_width="match_parent"
-
android:layout_height="wrap_content"
-
android:layout_weight="0"/>
-
-
<FrameLayout
-
android:id="@android:id/tabcontent"
-
android:layout_width="match_parent"
-
android:layout_height="0dip"
-
android:layout_weight="1"/>
-
-
</LinearLayout>
-
</TabHost>
发现整个过程和上面不继承TabActivity时相。还按照上面的情况,在两个xml文件中定义两个tab内容,由于在使用getTabHost()时,已经调用了SetContentView(),所以在下面的主文件中,就不用调用了。
layout11.xml和layout22.xml文件和上面一样,在这就不在列出。
主文件MainActivity.java如下:
-
public class MainActivity extends TabActivity {
-
TabHost mTabhost;
-
-
@Override
-
protected void onCreate(Bundle savedInstanceState) {
-
super.onCreate(savedInstanceState);
-
-
mTabhost = getTabHost();
-
-
LayoutInflater inflater = LayoutInflater.from(this);
-
-
inflater.inflate(R.layout.layout11, mTabhost.getTabContentView());
-
inflater.inflate(R.layout.layout22, mTabhost.getTabContentView()); //动态载入XML
-
-
-
TabHost.TabSpec spec1 = mTabhost.newTabSpec("11");
-
spec1.setIndicator("first");
-
spec1.setContent(R.id.layout1);
-
-
TabHost.TabSpec spec2 = mTabhost.newTabSpec("22");
-
spec2.setIndicator("two");
-
spec2.setContent(R.id.layout2);
-
-
mTabhost.addTab(spec1);
-
mTabhost.addTab(spec2);
-
}
-
}
运行结果显示和上面一样,只不过由于由于一个是继承AppCompatActivit(默认带导航栏)和一个是继承TabHost的缘故,造成了导航栏有无的区别。
3.搞清了TabHost的基础知识,就可以用它扩展实现一个底部导航功能。在这主要是为了学习OsChina客户端源码,下面是效果图:
整个实现是按照源码摘出来的,主要用到了FragmentTabHost,也用到枚举类来初始化Tab标签,另外,indicator的实现用到了xml布局样本,在此仅列出部分主要代码。
MainTab.java
-
package com.example.myapplication;
-
-
public enum MainTab {
-
-
NEWS(0, "综合", R.drawable.tab_icon_new, fragment1.class),
-
-
TWEET(1, "动弹", R.drawable.tab_icon_tweet, fragment2.class),
-
-
QUICK(2, "快速", R.drawable.tab_icon_new, null),
-
-
EXPLORE(3, "发现", R.drawable.tab_icon_explore, fragment3.class),
-
-
ME(4, "我", R.drawable.tab_icon_me, fragment4.class);
-
-
private int idx;
-
private String resName;
-
private int resIcon;
-
private Class<?> clz;
-
-
private MainTab(int idx, String resName, int resIcon, Class<?> clz) {
-
this.idx = idx;
-
this.resName = resName;
-
this.resIcon = resIcon;
-
this.clz = clz;
-
}
-
public int getIdx() {
-
return idx;
-
}
-
public void setIdx(int idx) {
-
this.idx = idx;
-
}
-
public String getResName() {
-
return resName;
-
}
-
public void setResName(String resName) {
-
this.resName = resName;
-
}
-
public int getResIcon() {
-
return resIcon;
-
}
-
public void setResIcon(int resIcon) {
-
this.resIcon = resIcon;
-
}
-
public Class<?> getClz() {
-
return clz;
-
}
-
public void setClz(Class<?> clz) {
-
this.clz = clz;
-
}
-
}
activity.xml,在这有一处不解
MyFragmentTabHost的id不能写为@android:id/tabhost,但源码确实是这样实现的,具体原因回头再找出吧。
-
<LinearLayout xmlns:android=""
-
xmlns:tools=""
-
android:layout_width="match_parent"
-
android:layout_height="match_parent"
-
android:orientation="vertical">
-
-
<FrameLayout
-
android:id="@+id/realtabcontent"
-
android:layout_width="match_parent"
-
android:layout_height="0dp"
-
android:layout_weight="1"></FrameLayout>
-
-
<FrameLayout
-
android:layout_width="match_parent"
-
android:layout_height="wrap_content"
-
android:background="#ffffff">
-
-
<RelativeLayout
-
android:layout_width="match_parent"
-
android:layout_height="wrap_content"
-
>
-
-
<com.example.myapplication.MyFragmentTabHost
-
android:id="@+id/tabhost"
-
android:layout_width="match_parent"
-
android:layout_height="wrap_content"
-
android:layout_marginTop="4dp">
-
</com.example.myapplication.MyFragmentTabHost>
-
-
<View
-
android:layout_width="match_parent"
-
android:layout_height="1px"
-
android:background="#D6D6D6" />
-
</RelativeLayout>
-
-
<ImageView
-
android:id="@+id/quick_option_iv"
-
android:layout_width="40dp"
-
android:layout_height="40dp"
-
android:layout_gravity="center"
-
android:layout_marginBottom="4dp"
-
android:layout_marginTop="4dp"
-
android:contentDescription="@null"
-
android:src="@drawable/btn_quickoption_selector" />
-
</FrameLayout>
-
</LinearLayout>
阅读(564) | 评论(0) | 转发(0) |