在本教程中,我们将概述Android布局。我们还将探讨一些特定的布局控件,用于组织屏幕内容,即Android LinearLayout和Android RelativeLayout。
Android布局
用户界面的基本构建块是从View类创建的View对象,它占据屏幕上的矩形区域。Views是UI组件(如TextView、Button、EditText等)的基类。ViewGroup是View的子类。一个或多个Views可以被组合成一个ViewGroup。ViewGroup提供了Android布局,我们可以在其中对视图的外观和顺序进行排序。ViewGroup的示例包括LinearLayout
、FrameLayout
、RelativeLayout
等。
Android布局类型
Android提供了以下ViewGroup或布局:
LinearLayout
:是一个ViewGroup,将所有子项在单个方向上垂直或水平对齐RelativeLayout
:是一个ViewGroup,以相对位置显示子视图AbsoluteLayout
:允许我们指定子视图和小部件的确切位置TableLayout
:是一种将其子视图分组为行和列的视图FrameLayout
:是屏幕上的占位符,用于显示单个视图ScrollView
:是一种特殊类型的FrameLayout,允许用户滚动查看占用比物理显示更多空间的视图列表。ScrollView只能包含一个子视图或ViewGroup,通常是LinearLayoutListView
:是显示可滚动项目列表的视图组GridView
:是显示二维滚动网格中项目的ViewGroup。网格中的项目来自与此视图关联的ListAdapter
在本教程中,我们将重点介绍两种最常用的安卓布局:
- LinearLayout
- RelativeLayout
安卓布局属性
- 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告诉视图变得与其父视图一样大。
视图标识
ID的XML标签内的语法为:
- 字符串开头的at符号(@)表示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
,其具有垂直方向,并包含按钮、文本视图和一个嵌套的线性布局(具有水平方向)作为子视图。注意:嵌套布局不必是一种类型。例如,我们可以在RelativeLayout的子元素中有一个LinearLayout,反之亦然。
Android RelativeLayout
Android RelativeLayout 根据元素彼此之间和与父容器的关系进行布局。这是最复杂的布局之一,我们需要多个属性才能实现我们想要的布局。也就是说,使用RelativeLayout,我们可以将视图定位为其兄弟视图的左侧、右侧、下方或上方。我们还可以将视图相对于其父视图定位,如水平居中、垂直居中或两者兼而有之,或与父RelativeLayout
的任何边缘对齐。如果在子视图上未指定这些属性中的任何一个,则默认将该视图呈现在左上位置。
Android RelativeLayout 属性
以下是跨RelativeLayout的三个不同类别中使用的主要属性:
相对于容器
- android:layout_alignParentBottom:将元素的底部放置在容器的底部
- android:layout_alignParentLeft:将元素的左侧放置在容器的左侧
- android:layout_alignParentRight:将元素的右侧放置在容器的右侧
- android:layout_alignParentTop:将元素放置在容器顶部
- android:layout_centerHorizontal:在其父容器中水平居中元素
- android:layout_centerInParent:在其容器中水平和垂直居中元素
- android:layout_centerVertical:在其父容器中垂直居中元素
相对于兄弟元素
- android:layout_above:将元素放置在指定元素的上方
- android:layout_below:将元素放置在指定元素的下方
- android:layout_toLeftOf:将元素放置在指定元素的左侧
- android:layout_toRightOf:将元素放置在指定元素的右侧
“@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="Back"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/firstName"
android:text="First Name"
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="JournalDev"
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="Layout Tutorial Example"
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="Last Name"
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="Next"
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="Parent RelativeLayout"
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="Nested Horizontal"
android:textSize="18sp"
android:layout_margin="10dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:text="LL"
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="Double Nested"
android:textSize="18sp"
android:layout_margin="10dp"
android:layout_gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:text="Vertical"
android:textSize="18sp"
android:layout_margin="10dp"
android:layout_gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:text="LL"
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="Nested Relative Layout"
android:id="@+id/textView"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true" />
<Button
android:id="@+id/back_button_pressed"
android:text="back"
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布局代码
应用程序启动到MainActivity,通过以下代码加载layout_linear.xml
的内容:
package com.journaldev.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();
}
});
}
}
SecondActivity
和 ThirdActivity
分别加载 layout_relative.xml
和 layout_mixed.xml
布局,如下所示:
package com.journaldev.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.journaldev.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 文档
Source:
https://www.digitalocean.com/community/tutorials/android-layout-linearlayout-relativelayout