布局及视图(四)

7、绝对布局(AbsoluteLayout)

绝对布局:是一个ViewGroup以绝对方式显示它的子视图(view)元素,即以坐标的方式来定位在屏幕上位置。

这种布局方式很好理解,在布局文件或编程地设置View的坐标,从而绝对地定位。如下所示布局文件:

<AbsoluteLayout xmlns:android="http://schemas.android.com/apk/res/android" 
   android:id="@+id/AbsoluteLayout01" 
   android:layout_width="fill_parent" 
   android:layout_height="fill_parent" 
   >
   <TextView android:id="@+id/txtIntro"
     android:text="绝对布局"
     android:layout_width="fill_parent"
     android:layout_height="wrap_content"
     android:layout_x="20dip"<!-- have an eye on ! -->
     android:layout_y="20dip"><!-- have an eye on ! -->
   </TextView>
</AbsoluteLayout>

 

简单吧,这里不在深入了!

8、标签布局(Tab Layout)

标签布局:是一个ViewGroup以标签的方式显示它的子视图(view)元素,就像在Firefox中的一个窗口中显示多个网页一样。

为了狂创建一个标签UI(tabbed UI),需要使用到TabHostTabWidgetTabHost必须是布局的根节点,它包含为了显示标签的TabWidget和显示标签内容的FrameLayout

可以有两种方式实现标签内容:使用标签在同一个活动中交换视图、使用标签在完全隔离的活动之间改变。根据你的需要,选择不同的方式,但是如果每个标签提供不同的用户活动,为每个标签选择隔离的活动,因此你可以更好地以分离的组管理应用程序,而不是一个巨大的应用程序和布局。下面还有一个例子来创建一个标签UI,每个标签使用隔离的活动。

1)、在项目中建立三个隔离的Activity类:ArtistisActivity、AlbumActivity、SongActivity。它们每个表示一个分隔的标签。每个通过TextView显示简单的一个消息,例如:

public class ArtistsActivity extends Activity {
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        TextView textview = new TextView(this);
        textview.setText("This is the Artists tab");
        setContentView(textview);
    }
}

 

其它两个类也类似。

2)、设置每个标签的图标,每个图标应该有两个版本:一个是选中时的,一个是未选中时的。通常的设计建议是,选中的图标应该是深色(灰色),未选中的图标是浅色(白色)。

现在创建一个state-list drawable指定哪个图标表示标签的状态:将图片放到res/drawable目录下并创建一个新的XML文件命名为ic_tab_artists.xml,内容如下:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- When selected, use grey -->
    <item android:drawable="@drawable/ic_tab_artists_grey"
          android:state_selected="true" />
    <!-- When not selected, use white-->
    <item android:drawable="@drawable/ic_tab_artists_white" />
</selector>

 

3)、res/layour/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">
    <LinearLayout
        android:orientation="vertical"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:padding="5dp">
        <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"
            android:padding="5dp" />
    </LinearLayout>
</TabHost>

 

这个布局将显示标签和提供上面创建的活动之间的导航。TabHost要求包含一个TabWidget和一个FrameLayoutTabWidgetFrameLayoutTabHost以线性垂直地显示。

4)、HelloWorld.java文件源码如下:

package skynet.com.cnblogs.www;

import android.widget.TabHost;
import android.app.TabActivity;
import android.content.Intent;
import android.content.res.Resources;
import android.os.Bundle;

public class HelloWorld extends TabActivity{
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        Resources res = getResources(); // Resource object to get Drawables
        TabHost tabHost = getTabHost();  // The activity TabHost
        TabHost.TabSpec spec;  // Resusable TabSpec for each tab
        Intent intent;  // Reusable Intent for each tab

        // Create an Intent to launch an Activity for the tab (to be reused)
        intent = new Intent().setClass(this, ArtistsActivity.class);

        // Initialize a TabSpec for each tab and add it to the TabHost
        spec = tabHost.newTabSpec("artists").setIndicator("Artists",
                          res.getDrawable(R.drawable.ic_tab_artists))
                      .setContent(intent);
        tabHost.addTab(spec);

        // Do the same for the other tabs
        intent = new Intent().setClass(this, AlbumsActivity.class);
        spec = tabHost.newTabSpec("albums").setIndicator("Albums",
                          res.getDrawable(R.drawable.ic_tab_artists))
                      .setContent(intent);
        tabHost.addTab(spec);

        intent = new Intent().setClass(this, SongsActivity.class);
        spec = tabHost.newTabSpec("songs").setIndicator("Songs",
                          res.getDrawable(R.drawable.ic_tab_artists))
                      .setContent(intent);
        tabHost.addTab(spec);

        tabHost.setCurrentTab(2);
    }
}

 

 

 

设置每个标签的文字和图标,并分配每个标签一个活动(这里为了方便三个标签都有相同的图标)。TabHost的引用第一次通过getTabHost()获取。然后,为每个标签,创建TabHost.TabSpec定义标签的属性。newTabSpec(String)方法创建一个新的TabHost.TabSpec以给定的字符串标识标签。调用TabHost.TabSpec, setIndicator(CharSequence, Drawable)为每个标签设置文字和图标,调用setContent(Intent)指定Intent去打开合适的活动。每个TabHost.TabSpec通过调用addTab(TabHost.TabSpec)添加到TabHost。

最后,setCurrentTab(int)设置打开默认显示的标签,通过索引标签的位置。

5)、打开Android的清单文件AndroidManifest.xml,添加NoTitleBar主题到HelloWorld的<activity>标记。这将移除默认应用程序的标题和顶端布局,给标签腾出位置。<activity>标记应该像这样:

        <activity android:name=".HelloWorld"
                  android:label="@string/app_name"
                  android:theme="@android:style/Theme.NoTitleBar">

 

你运行这个程序能够得到什么结果呢?请自行检查。不过我在这里告诉你很有可能会运行不了,报“java.lang.NullPointerException”错!我想运行这个例子的很多人都会有这个问题,不信你试试!

PS:其实这也算是Android的一个bug,而且这个bug在2.2中还没有解决,这个问题全球N多人都碰到了,并在http://code.google.com/p/android/issues中挂号了,相关问题的编号有不止一个。

接着往下看……

如果你看了我这篇文章,你一定会是个幸运儿!经过我艰苦的调试+找资料,我找到了解决方法:

在清单文件AndroidManifest.xml,添加下面三个Activity:

<activity android:name=".AlbumsActivity"  android:label="@string/app_name"></activity>
<activity android:name=".ArtistsActivity" android:label="@string/app_name"></activity>
<activity android:name=".SongsActivity"  android:label="@string/app_name"></activity>

现在运行可以看到如下结果:

tablayout图9、标签布局

posted @ 2011-03-12 15:39  OAKPIP  阅读(368)  评论(0编辑  收藏  举报