乐者为王

Do one thing, and do it well.

Android Tab导航总结

TabHost包括TabWidget和FrameLayout两部分:TabWidget用于展示标签页,FrameLayout用于展示隶属于各个标签页的具体内容。一个带有TabHost的Activity看起来就像这样:

android-tabs

如果Activity是继承自TabAcitivty,那么TabHost的id必须设置为@android:id/tabhost,TabWidget必须设置为@android:id/tabs,FrameLayout需要设置为@android:id/tabcontent。

1、创建一个简单的Tab应用

废话不多说,直接上代码。以下就是main.xml的布局代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?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">
    <LinearLayout
        android:orientation="vertical"
        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="fill_parent">
            <include android:id="@+id/left" layout="@layout/tab_left" />
            <include android:id="@+id/right" layout="@layout/tab_right" />
        </FrameLayout>
    </LinearLayout>
</TabHost>

左边标签页tab_left.xml的内容:

1
2
3
4
5
6
7
8
9
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <TextView
        android:text="left"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" />
</LinearLayout>

右边标签页tab_right.xml的内容:

1
2
3
4
5
6
7
8
9
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <TextView
        android:text="right"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" />
</LinearLayout>

MainActivity需要从TabActivity继承:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class MainActivity extends TabActivity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        TabHost tabHost = getTabHost();
        tabHost.addTab(tabHost.newTabSpec("left")
                .setIndicator("Left")
                .setContent(R.id.left));
        tabHost.addTab(tabHost.newTabSpec("right")
                .setIndicator("Right")
                .setContent(R.id.right));
        tabHost.setCurrentTab(0);
    }
}

到这里,一个简单至极的Tab应用已经完成了。不过在实际情况中,每个Tab页会有多个控件,并且有很多业务逻辑在其中。如果使用上述代码,将所有控件和逻辑放在一个类中,那么这个类将变的极度臃肿,以后维护也会变的非常困难。需要找个简单且优雅的方案解决这个问题。

2、简单优雅且容易维护的Tab应用

上面的实现有个缺陷,标签页相关的代码逻辑都在MainActivity类中,导致单个类臃肿,给后续维护造成不便。可以考虑把相关的代码逻辑移到对应的类中。

删除main.xml中的include语句:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?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">
    <LinearLayout
        android:orientation="vertical"
        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="fill_parent" />
    </LinearLayout>
</TabHost>

新建TabLeftActivity和TabRightActivity类:

1
2
3
4
5
6
7
8
9
10
public class TabLeftActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.tab_left);

        // do something
    }
}
1
2
3
4
5
6
7
8
9
10
public class TabRightActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.tab_right);

        // do something
    }
}

修改MainAcvitity为如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class MainActivity extends TabActivity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        TabHost tabHost = getTabHost();
        tabHost.addTab(tabHost.newTabSpec("left")
                .setIndicator("Left")
                .setContent(new Intent(this, TabLeftActivity.class)));
        tabHost.addTab(tabHost.newTabSpec("right")
                .setIndicator("Right")
                .setContent(new Intent(this, TabRightActivity.class)));
        tabHost.setCurrentTab(0);
    }
}

最后,不要忘记在AndroidManifest.xml中注册TabLeftActivity和TabRightAcvitity这两个Activity。

3、如何将Tab显示在下方

这个非常简单,只要将main.xml中的LinearLayout改成RelativeLayout,然后给TagWidget添加android:layout_alignParentBottom="true"属性即可。当然也可以在main.xml中把TabWidget放在FrameLayout下面。

Comments