Android用户界面设计:线性布局

时间:2024-03-24 16:32:18

什么是线性布局

线性布局是最简单,Android开发者使用得最多的布局类型之一,开发者用它来组织你们的用户界面上的控件。线性布局的作用就像它的名字一样:它将控件组织在一个垂直或水平的形式。当布局方向设置为垂直时,它里面的所有子控件被组织在同一列中;当布局方向设置为水平时,所有子控件被组织在一行中。

线性布局可以在XML布局资源文件中定义,也可以用Java代码在程序中动态的定义。

下图展示了一个包含7个TextView控件的线性布局。这个线性布局方向被设置为垂直,导致每个TextView控件被显示在一列当中。每一个TextView控件的文本属性都是一个颜色值,背景色就是这个颜色;通过将控件的layout_width属性设置为fill_parent,每个控件都拉伸到屏幕宽度。

Android用户界面设计:线性布局

用XML布局资源定义线性布局

设计程序用户界面最方便和可维护的方法是创建XML布局资源。这个方法极大地简化了UI设计过程,它将很多静态创建和用户界面控件的布局以及控件属性的定义移到了XML中,而不是写代码。

XML布局资源必须被存储在项目目录的/res/layout下。让我们看看前一节介绍的彩虹线性布局。这个屏幕基本上就是一个设置为铺满整个屏幕的垂直线性布局,这通过设置它的layout_width和layout_height属性为fill_parent来实现。适当地将其命名为/res/layout/rainbow.xml,XML定义如下:


  1. <?xmlversion="1.0"encoding="utf-8"?>
  2. <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="fill_parent"android:layout_height="fill_parent"
  4. android:orientation="vertical">
  5. <TextViewandroid:text="RED"android:id="@+id/TextView01"
  6. android:layout_height="wrap_content"android:background="#f00"
  7. android:layout_width="fill_parent"android:layout_weight=".14"
  8. android:gravity="center"android:textColor="#000"></TextView>
  9. <TextViewandroid:text="ORANGE"android:id="@+id/TextView02"
  10. android:layout_height="wrap_content"android:layout_width="fill_parent"
  11. android:layout_weight=".15"android:background="#ffa500"
  12. android:gravity="center"android:textColor="#000"></TextView>
  13. <TextViewandroid:text="YELLOW"android:id="@+id/TextView03"
  14. android:layout_height="wrap_content"android:layout_width="fill_parent"
  15. android:layout_weight=".14"android:background="#ffff00"
  16. android:gravity="center"android:textColor="#000"></TextView>
  17. <TextViewandroid:text="GREEN"android:id="@+id/TextView04"
  18. android:layout_height="wrap_content"android:layout_width="fill_parent"
  19. android:layout_weight=".15"android:background="#0f0"android:gravity="center"
  20. android:textColor="#000"></TextView>
  21. <TextViewandroid:text="BLUE"android:id="@+id/TextView05"
  22. android:layout_height="wrap_content"android:layout_width="fill_parent"
  23. android:layout_weight=".14"android:background="#00f"android:gravity="center"
  24. android:textColor="#fff"></TextView>
  25. <TextViewandroid:text="INDIGO"android:id="@+id/TextView06"
  26. android:layout_height="wrap_content"android:layout_width="fill_parent"
  27. android:layout_weight=".14"android:background="#4b0082"
  28. android:gravity="center"android:textColor="#fff"></TextView>
  29. <TextViewandroid:text="VIOLET"android:id="@+id/TextView07"
  30. android:layout_height="wrap_content"android:layout_width="fill_parent"
  31. android:layout_weight=".14"android:background="#ee82ee"
  32. android:gravity="center"android:textColor="#000"></TextView>
  33. </LinearLayout>

可能你会注意到这个线性布局的每一个子控件都有很多有趣的属性,包括一个叫做layout_weight的属性。一会我们会讲到更多关于它的内容。

下面两张图片展示了这个布局在设备的竖屏和横屏模式下的样子:

Android用户界面设计:线性布局

Android用户界面设计:线性布局

回忆一下,在Activity中,只需要一行有onCreate()方法的代码来在屏幕上加载和显示一个布局资源。如果这个布局资源被存储在/res/layout/rainbow.xml文件中,这行代码应该是:


  1. setContentView(R.layout.rainbow);
  2. 用程序动态定义线性布局

    你也可以通过程序来创建和配置线性布局。这通过LinearLayout(android.widget.LinearLayout)类来实现。你能在LinearLayout.LayoutParams类中找到子级细节。同样地,典型的布局参数(android.view.ViewGroup.LayoutParams),如layout_height和layout_width, 以及边距参数(ViewGroup.MarginLayoutParams)也能用在LinearLayout对象上。

    使用以前介绍过的setContentView()方法代替直接加载布局资源,你需要用Java创建屏幕内容,然后向setContentView()方法提供一个父级布局对象,这个对象包括了所有要作为它的子视图展示的控件内容。在这种情况下,你的父级布局对象是线性布局。

    例如,下面的代码示例了如何用程序在Activity中实例化一个线性布局并在它的onCreate()方法中将三个TextView对象放入其中:

    
    
    1. publicvoidonCreate(BundlesavedInstanceState){
    2. super.onCreate(savedInstanceState);
    3. //setContentView(R.layout.rainbow);
    4. TextViewtv1=newTextView(this);
    5. tv1.setText("FIRST");
    6. tv1.setTextSize(100);
    7. tv1.setGravity(Gravity.CENTER);
    8. TextViewtv2=newTextView(this);
    9. tv2.setTextSize(100);
    10. tv2.setGravity(Gravity.CENTER);
    11. tv2.setText("MIDDLE");
    12. TextViewtv3=newTextView(this);
    13. tv3.setTextSize(100);
    14. tv3.setGravity(Gravity.CENTER);
    15. tv3.setText("LAST");
    16. LinearLayoutll=newLinearLayout(this);
    17. ll.setOrientation(LinearLayout.VERTICAL);
    18. ll.setLayoutParams(newLayoutParams(LayoutParams.FILL_PARENT,LayoutParams.FILL_PARENT));
    19. ll.setGravity(Gravity.CENTER);
    20. ll.addView(tv1);
    21. ll.addView(tv2);
    22. ll.addView(tv3);
    23. setContentView(ll);
    24. }

    下面两张图片展示了这个布局在设备竖屏和横屏下的样子:

    Android用户界面设计:线性布局

    Android用户界面设计:线性布局

    让我们更近一步地研究一下上面的Java代码。首先,创建并配置三个TextView控件。每个控件都有文本大小(字体大小),文本对齐,以及文本值本身。然后,创建一个垂直方向的线性布局。它的布局参数允许它填充整个父级对象(在这里就是整个屏幕),并且它的对齐导致所有子控件都排列在屏幕中间,而不是从左上角开始。每个TextView控件通过addView方法作为子控件添加到线性布局中。最后,当父级控件要在屏幕上显示时,线性布局被传到setContentView()方法中。

    如你所见,当越来越多的控件要添加到屏幕时,代码量会很快地增长。为了易组织和可维护性,用程序定义并使用布局最好是用在特殊情况而不是一般情况。


  3. 探讨线性布局的重要特性和属性

    现在让我们来看看有助于配置线性布局和它的子控件的一些重要属性。

    一些特别的属性应用到线性布局。你会使用到线性布局最重要的属性包括:

    ◆方向属性(必须),取值可以是vertical或horizontal(类:LinearLayout)

    ◆对齐属性(可选),控制子控件在线性布局中如何排列和显示(类:LinearLayout)

    ◆layout_weight属性(可选,应用到每个子控件)指定每个子控件在父级线性布局中的相对重要性(类:LinearLayout.LayoutParams)

    此外,通用的ViewGroup-style属性也应用到线性布局。这些属性包括:

    ◆通用布局参数如layout_height (必须)和layout_width (必须) (类:ViewGroup.LayoutParams)

    ◆边距布局参数如margin_top,margin_left,margin_right和margin_bottom (类:ViewGroup. MarginLayoutParams)

    ◆布局参数如layout_height和layout_width (类:ViewGroup.LayoutParams)

    给子控件赋权

    绝大部分线性布局的属性都是自明性的。然而layout_weight属性需要一些额外的讨论。与其它线性布局属性不同,其它属性应用在线性布局视图本身,而这个属性是应用在它的子控件上的。权值本身应该是一个数字(比如0.5,0.25,0.10,0.10,0.05),如果你把所有子控件的权值加起来等于1(100%)。

    子控件的权值控件它在父线性布局中有多“重要”或者留给其多少“空间”。这一点最好通过例子来说明。让我们回到我们前面用的彩虹线性布局。为了允许所有子控件相同地“拉伸”填充线性布局,不管屏幕的大小,我们使用layout_weight来对每个TextView赋予相对权值。因为有7种我们想赋相同权值的颜色,我们将1除以7大约得到0.143.然而,既然我们想要权值之和最后为1,因此5个控件权值设为0.14,另外两个为0.15——一个微小的区别使得总和刚刚好为1,但是这对于第一个和最后一个控件来说还是很明显的。

    当屏幕上有足够空间来正确的展示所有控件的时候,这个权值技巧很有效。那就是说,当空间很紧的时候,权值属性可能会被其它因素覆盖,比如视图裁剪或者在TextView下试图不环绕文本。当我们改变rainbow.xml布局文件以包含相似水平布局(layout_height 还是设置为 fill_parent)的时候,这变得很明显。

    下面的两张图片展示这个相同的布局(只是改变到水平方向)在设备竖屏和横屏模式下可能的样子:

    Android用户界面设计:线性布局

    Android用户界面设计:线性布局

    我们期望的是红色和紫色区域(权值0.15)比其它颜色(权值为0.14)会略大一些,但是显示出来却不是这样。如果你仔细看红色TextView,它应该比它边上橙色的TextView占用更多空间。然而,因为“Red”是一个短单词,而“Orange”不是,因此系统自动的作了一些冲撞调整,为了使得每个单词不会折行。这样的结果更令人高兴,但是这可能会有一些烦恼,如果这不是想要的效果的话。