Android布局完全指南:详解线性布局(LinearLayout)与相对布局(RelativeLayout)
这是文章《Android布局 – 线性布局(LinearLayout),相对布局(RelativeLayout)》的第1部分(共4部分)。
在本教程中,我们将提供Android布局的概述。我们还将探讨一些专门用于组织屏幕内容的布局控件,即Android线性布局(LinearLayout)和Android相对布局(RelativeLayout)。
Android布局
Android用户界面的基本构建块是从View类创建的View对象,占据屏幕上的矩形区域。View是UI组件如TextView、Button、EditText等的基类。ViewGroup是View的子类。一个或多个View可以被组合成一个ViewGroup。ViewGroup提供了Android布局,我们可以对视图的外观和顺序进行排列。线性布局(LinearLayout)、框架布局(FrameLayout)、相对布局(RelativeLayout)等都是ViewGroup的例子。
Android布局类型
安卓提供了以下的ViewGroups或布局:
- 线性布局(LinearLayout):是一个布局容器,将所有子视图在一个方向上进行对齐,可以是垂直或水平对齐。
- 相对布局(RelativeLayout):是一个布局容器,以相对位置显示子视图。
- 绝对布局(AbsoluteLayout):允许我们指定子视图和小部件的确切位置。
- 表格布局(TableLayout):是一个视图,将其子视图分组成行和列。
- 框架布局(FrameLayout):是屏幕上的占位符,用于显示单个视图。
- 滚动视图(ScrollView):是一种特殊类型的FrameLayout,允许用户滚动浏览占用比物理显示更多空间的视图列表。ScrollView只能包含一个子视图或ViewGroup,通常是LinearLayout。
- 列表视图(ListView):是一个视图组,用于显示可滚动的列表项。
- 网格视图(GridView):是一个布局容器,以二维滚动网格显示项目。网格中的项目来自与该视图关联的ListAdapter。
在这个教程中,我们将专注于两个最常使用的Android布局:
- 线性布局(LinearLayout)
- 相对布局(RelativeLayout)
Android布局属性
- android:id:这是唯一标识视图的ID。
- android:layout_width:这是布局的宽度。
- android:layout_height:这是布局的高度。
- android:layout_margin:这是视图外部的额外空间。例如,如果给定android:marginLeft=20dp,那么视图将在离左侧20dp之后布局。
- android:layout_padding:这类似于android:layout_margin,不同之处在于它指定了视图内部的额外空间。
- android:layout_gravity:这指定了子视图的位置。
- android:layout_weight:这指定了布局中额外空间应该分配给视图的大小。
- android:layout_x:这指定了布局的x坐标。
- android:layout_y:这指定了布局的y坐标。
android:layout_width=wrap_content
告诉视图根据所需的内容来决定自己的尺寸。android:layout_width=match_parent
告诉视图变得与其父视图一样大。
查看身份认证
XML标签中的ID语法为:
- 字符串开头的@符号表示XML解析器应该解析并展开ID字符串的其余部分,并将其标识为ID资源。
- 加号(+)表示这是一个新的资源名称,必须创建并添加到我们的资源中。
安卓(Android)线性布局(LinearLayout)
Android的LinearLayout将元素沿一条直线进行组织。我们可以使用android:orientation来指定该线是垂直还是水平。默认情况下,方向是水平的。垂直LinearLayout每行只有一个子元素(因此是单个元素的列),而水平LinearLayout在屏幕上只有一行单个元素。android:layout_weight属性描述了元素的重要性。具有较大权重的元素占用更多的屏幕空间。以下是使用LinearLayout的示例布局XML:layout_linear.xml
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_margin="@dimen/activity_horizontal_margin">
<Button
android:id="@+id/backbutton"
android:text="Back"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:text="Row 2"
android:layout_width="wrap_content"
android:textSize="18sp"
android:layout_margin="10dp"
android:layout_height="wrap_content" />
<TextView
android:text="Row 3"
android:textSize="18sp"
android:layout_margin="10dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:text="Row 4"
android:textSize="18sp"
android:layout_margin="10dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:text="Row 5"
android:textSize="18sp"
android:layout_margin="10dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:id="@+id/next_button"
android:text="next"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:text="Row 6b"
android:textSize="18sp"
android:layout_margin="10dp"
android:layout_gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:text="Row 6c"
android:textSize="18sp"
android:layout_margin="10dp"
android:layout_gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:text="Row 6d"
android:textSize="18sp"
android:layout_margin="10dp"
android:layout_gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>
在这个布局中,我们有一个父LinearLayout,它具有垂直方向,并包含按钮、文本视图和一个嵌套的LinearLayout(具有水平方向)作为子视图。注意:嵌套的布局不需要是相同类型的。例如,我们可以在RelativeLayout的子视图中有一个LinearLayout,反之亦然。
安卓的RelativeLayoutAndroid的RelativeLayout是根据元素之间的关系以及与父容器的关系来进行布局的。这是最复杂的布局之一,我们需要多个属性来实现我们想要的布局。也就是说,使用RelativeLayout,我们可以将一个视图放置在其兄弟视图的左侧、右侧、下方或上方。我们还可以根据父视图来定位一个视图,例如水平、垂直或两者居中,或者与父RelativeLayout的任何边对齐。如果在子视图上没有指定这些属性中的任何一个,那么该视图默认呈现在左上角位置上。
安卓的RelativeLayout属性以下是在RelativeLayout中使用的主要属性。它们分属于三个不同的类别。
关于容器
- android:layout_alignParentBottom : Places the bottom of the element on the bottom of the container
- android:layout_alignParentLeft : Places the left of the element on the left side of the container
- android:layout_alignParentRight : Places the right of the element on the right side of the container
- android:layout_alignParentTop : Places the element at the top of the container
- android:layout_centerHorizontal : Centers the element horizontally within its parent container
- android:layout_centerInParent : Centers the element both horizontally and vertically within its container
- android:layout_centerVertical : Centers the element vertically within its parent container
相对于兄弟姐妹
- android:layout_above : Places the element above the specified element
- android:layout_below : Places the element below the specified element
- android:layout_toLeftOf : Places the element to the left of the specified element
- android:layout_toRightOf : Places the element to the right of the specified element
关于容器
- android:layout_alignParentBottom : Places the bottom of the element on the bottom of the container
- android:layout_alignParentLeft : Places the left of the element on the left side of the container
- android:layout_alignParentRight : Places the right of the element on the right side of the container
- android:layout_alignParentTop : Places the element at the top of the container
- android:layout_centerHorizontal : Centers the element horizontally within its parent container
- android:layout_centerInParent : Centers the element both horizontally and vertically within its container
- android:layout_centerVertical : Centers the element vertically within its parent container
相对于兄弟姐妹
- android:layout_above : Places the element above the specified element
- android:layout_below : Places the element below the specified element
- android:layout_toLeftOf : Places the element to the left of the specified element
- android:layout_toRightOf : Places the element to the right of the specified element
- android:layout_above : Places the element above the specified element
- android:layout_below : Places the element below the specified element
- android:layout_toLeftOf : Places the element to the left of the specified element
- android:layout_toRightOf : Places the element to the right of the specified element
“@id/XXXXX” 是用来通过元素的 id 进行引用。需要记住的一件事是,在元素被声明之前引用它会产生错误,因此在这种情况下应该使用 @+id/。
与其他元素的协调
- android:layout_alignBaseline : 将新元素的基线与指定元素的基线对齐
- android:layout_alignBottom : 将新元素的底部与指定元素的底部对齐
- android:layout_alignLeft : 将新元素的左边缘与指定元素的左边缘对齐
- android:layout_alignRight : 将新元素的右边缘与指定元素的右边缘对齐
- android:layout_alignTop : 将新元素的顶部与指定元素的顶部对齐
以下的XML布局使用了相对布局(RelativeLayout):layout_relative.xml
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
xmlns:android="https://schemas.android.com/apk/res/android">
<Button
android:id="@+id/backbutton"
android:text="返回"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/firstName"
android:text="名字"
android:textSize="18sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/backbutton" />
<TextView
android:id="@+id/editFirstName"
android:text="开发示例"
android:textSize="18sp"
android:layout_width="wrap_content"
android:layout_marginLeft="10dp"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/firstName"
android:layout_below="@id/backbutton"/>
<TextView
android:id="@+id/editLastName"
android:text="布局教程示例"
android:textSize="18sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignTop="@+id/lastName"
android:layout_toRightOf="@+id/lastName"
android:layout_toEndOf="@+id/lastName" />
<TextView
android:id="@+id/lastName"
android:text="姓氏"
android:textSize="18sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="48dp"
android:layout_below="@+id/firstName"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_marginRight="10dp"
android:layout_marginLeft="40dp"
android:layout_marginStart="40dp" />
<Button
android:id="@+id/next"
android:text="下一步"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/editLastName"
android:layout_alignLeft="@+id/editLastName"
android:layout_alignStart="@+id/editLastName"
android:layout_marginTop="37dp" />
</RelativeLayout>
正如你所看到的,我们可以根据元素的相对位置重新排列它们。下面的XML布局代表了一个具有嵌套的线性布局和相对布局的自定义布局。layout_mixed.xml
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
xmlns:android="https://schemas.android.com/apk/res/android">
<TextView
android:id="@+id/parent_rl"
android:text="父级相对布局"
android:textSize="18sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/linearLayout"
android:layout_below="@id/parent_rl"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true">
<TextView
android:text="嵌套水平布局"
android:textSize="18sp"
android:layout_margin="10dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:text="线性布局"
android:textSize="18sp"
android:layout_margin="10dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<LinearLayout
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:text="双重嵌套"
android:textSize="18sp"
android:layout_margin="10dp"
android:layout_gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:text="垂直布局"
android:textSize="18sp"
android:layout_margin="10dp"
android:layout_gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:text="线性布局"
android:textSize="18sp"
android:layout_margin="10dp"
android:layout_gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/linearLayout">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="嵌套相对布局"
android:id="@+id/textView"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true" />
<Button
android:id="@+id/back_button_pressed"
android:text="返回"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/textView"
android:layout_centerHorizontal="true"
android:layout_marginTop="66dp" />
</RelativeLayout>
</RelativeLayout>
Android布局项目结构
Android布局项目实现
该项目包含三个Activity(活动)以及前面讨论过的相应布局。
Android布局代码实现
应用程序启动时进入MainActivity,通过以下代码加载layout_linear.xml文件中的内容:
package com.Olivia.layouts;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
Button back,next;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_linear);
back=(Button)findViewById(R.id.back_button);
next=(Button)findViewById(R.id.next_button);
next.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent=new Intent(MainActivity.this,SecondActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
}
});
back.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
}
}
第二个Activity(SecondActivity)和第三个Activity(ThirdActivity)分别加载layout_relative.xml和layout_mixed.xml布局,如下所示:
package com.Olivia.layouts;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class SecondActivity extends Activity {
Button back,next;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_relative);
back=(Button)findViewById(R.id.backbutton);
next=(Button)findViewById(R.id.next);
next.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent=new Intent(SecondActivity.this,ThirdActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
}
});
back.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent=new Intent(SecondActivity.this,MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
}
});
}
}
package com.Olivia.layouts;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class ThirdActivity extends Activity {
Button back;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_mixed);
back=(Button)findViewById(R.id.back_button_pressed);
back.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent=new Intent(ThirdActivity.this,SecondActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
}
});
}
}
布局文件效果展示
下面展示了三个布局文件的图像输出:
layout_linear.xml 可以看到,父LinearLayout由6个子元素组成,位于一个垂直列中,其中一个是包含4个水平方向组件的嵌套LinearLayout子视图。
layout_relative.xml 上面图像中的箭头描述了兄弟元素相对于彼此和容器的位置。
layout_mixed.xml 这个相对布局包含一个垂直LinearLayout和一个嵌套的水平LinearLayout,以及一个子RelativeLayout。注意:属于不同布局的组件不是兄弟元素,因此不能相对于彼此定位。它们的容器布局是兄弟元素,可以相对于彼此定位。如果你想知道蓝色边框矩形和箭头是什么,那是因为这些图片来自图形视图中的xml布局。当你运行应用时,这些蓝色线条和矩形将不会显示。
总结与后续
这就是Android布局教程的结束。我们将在下一个教程中介绍其他Android布局。你可以从下面的链接下载最终的Android布局项目。
下载 Android LinearLayout RelativeLayout 示例项目。
参考:API文档