Android学习笔记----布局
概述
项目开发中我们常常说的布局,其实就是指的应用的界面结构,布局中的所有元素均使用 View 和 ViewGroup 对象进行构建。View 通常是指用户可查看、可进行交互的内容。ViewGroup 则是不可见容器,用于定义 View 和其他 ViewGroup 对象的布局结构,如下图所示(图片来自google文档)。
View,多指控件,比如Button、EditText、TextView。ViewGroup对象通常被称为布局,比如说LinearLayout、FrameLayout。
通过两种方式声明布局:
- 在 XML 中声明界面元素。Android 提供对应 View 类及其子类的简明 XML 词汇,也可使用 Android Studio 的 Layout Editor,采用拖动方式来构建 XML 布局。
- 在运行时实例化布局元素。通过代码动态创建 View 对象和 ViewGroup 对象,并设置属性。
XML文件
android的xml文件编写其实很简单,根据android提供的xml词汇,按照既定的规则即可完成xml文件的编写。其规格如下:
- 每个布局文件都必须只包含有一个根元素,并且该元素必须是视图对象或者ViewGroup对象
- 文件已“.xml”为扩展名,并将文件保存在项目的 res/layout/ 目录中。
定义根元素后,就可以将其他布局或者控件当做子元素进行添加,从未构建出需要的界面。
一个简单的xml文件代码:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="返回"
android:id="@+id/btn_back">
</Button>
</LinearLayout>
加载XML文件
当编译项目的时候,系统会将每个XML文件编译成View资源。在Activity.onCreate()回调内,通过调用setContentView(R.layout.layout_file_name)向应用传递布局资源引用,当启动应用时,即可看到xml中的内容,示例代码如下:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(LOG_TAG,"onCreate");
setContentView(R.layout.activity_main);
}
属性
每个 View 对象和 ViewGroup 对象均支持自己的各个 XML 属性。某些属性是 View 对象的特有属性(例如,TextView 支持 textSize 属性),扩展类会继承View 对象的这些属性。某些属性是所有 View 对象的共有属性,因为它们继承自 View 根类(例如 id 属性)。此外,其他属性被视为“布局参数”,即描述 View 对象特定布局方向的属性。
共有属性–ID
每个View对象都可以拥有与之关联的整型ID,整型ID也是该View在结构树中的唯一标示。在布局XML文件中,系统通常会以字符串的方式定义ID,但是在编译后,系统会以整数形式引用此ID。示例代码如下:
android:id="@+id/btn_back"
字符串开头处的 @ 符号会告诉 XML 解析器应解析并展开 ID 字符串的其余部分,并将其标识为 ID 资源。加号 (+) 表示这是一个新的资源名称,必须创建该名称并将其添加到我们的资源(在 R.java 文件中)内。
ID无需保证在整个结构树中具有唯一性,但是要保证它在需要搜索的结构树中具有唯一性。通常我们要搜索的是整个结构树,所以还是保证ID的唯一性比较好。
布局参数
XML文件中,名为layout_xxx的属性可以认为是适合其在ViewGroup中的布局参数。
每个ViewGroup类都会实现一个扩展ViewGro.LayoutParams的嵌套类。如下图所示(图片来自google文档):
注意:
*每个LayoutParams子类都有自己值的设置语法。每个子元素都必须定义适合其父元素的LayoutParams,但父元素可以为它的子元素定义不同的LayoutParams。
所有的控件(View和ViewGroup)都必须设置宽度和高度(layout_width和layout_height),可以设置具体值,也可以使用wrap_content和match_parent。
设置控件大小的时候,不建议使用绝对单位(像素)。更好的办法是使用相对测量单位,比如与密度无关的像素单位dp、wrap_content和match_parent。这些有助于做不同分辨率下设备的适配。
控件尺寸
第一组称为测量宽度和测量高度。这些尺寸定义的是在父元素内具体的大小。可通过调用 getMeasuredWidth() 和 getMeasuredHeight() 来获得尺寸。
第二组简称为宽度和高度,有时也称为绘制宽度和绘制高度。这些尺寸是在定义绘制时和布局后,控件在屏幕上的实际尺寸。这些值可以(但不必)与测量宽度和测量高度不同。通过调用 getWidth() 和 getHeight() 来获得宽度和高度。
常见的布局
线性布局:LinearLayout,相对布局:RelativeLayout,帧布局:FrameLayout,这里先简单介绍下非常常用的LinearLayout和RealtiveLayout
线性布局LinearLayout
用于使所有子控件在单个方向(垂直或水平)保持对齐。
android:orientation="vertical"
android:orientation="horizontal"
当LinearLayout的宽或者高设置为match_parent(满屏)时,可以通过android:gravity设置其子控件的对其方式。
android:gravity="center"
LinearLayout支持使用android:layout_weight为子控件设置权重。该属性会根据“weight”值的大小,在屏幕上分配占据的空间大小。权重值越大则分配的空间也就越大。默认的权重为0。
均等分布时,需要将每个子控件的高度或者宽度设置为0dp(wrap_content也可以,但是效果和0dp时不太一样),同时将每个子控件的layout_weight设置为1。
不等分布时,修改layout_weight的值,设置为不同大小即可。示例代码如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:orientation="vertical"
android:layout_weight="2"
android:gravity="center">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="top"
android:id="@+id/btn_top">
</Button>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:orientation="vertical"
android:layout_weight="1">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="mid"
android:id="@+id/btn_mid">
</Button>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:orientation="vertical"
android:layout_weight="1">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="bottom"
android:id="@+id/btn_bottom">
</Button>
</LinearLayout>
</LinearLayout>
相对布局RelativeLayout
最适合做各个不同分辨率适配的布局。是一个非常强大的界面设计实用工具,因为它可以消除布局复杂的嵌套,并布局层次结构保持扁平化,从而提高性能。如果一个界面使用了多个嵌套的 LinearLayout 组,那么RelativeLayout的话,只需要一个就可以替换它们。
RelativeLayout规定其子元素必须定义ID,子元素可以根据彼此ID确定位置,常用的参数如下:
android:layout_alignParentTop 设置为 "true"时,会将此控件的上边缘与父控件的上边缘对齐。
android:layout_centerVertical 设置为 "true"时,会将此子级在父级内垂直居中。
android:layout_below 将此控件的上边缘放置在指定ID的控件下方。
android:layout_toRightOf 将此视图的左边缘放置在指定ID的控件右侧。
官网提供的具体属性以及解释:
参数名 | 原汁原味的解释 |
---|---|
android:layout_above | Positions the bottom edge of this view above the given anchor view ID. |
android:layout_alignBaseline | Positions the baseline of this view on the baseline of the given anchor view ID. |
android:layout_alignBottom | Makes the bottom edge of this view match the bottom edge of the given anchor view ID. |
android:layout_alignEnd | Makes the end edge of this view match the end edge of the given anchor view ID. |
android:layout_alignLeft | Makes the left edge of this view match the left edge of the given anchor view ID. |
android:layout_alignParentBottom | If true, makes the bottom edge of this view match the bottom edge of the parent. |
android:layout_alignParentEnd | If true, makes the end edge of this view match the end edge of the parent. |
android:layout_alignParentLeft | If true, makes the left edge of this view match the left edge of the parent. |
android:layout_alignParentRight | If true, makes the right edge of this view match the right edge of the parent. |
android:layout_alignParentStart | If true, makes the start edge of this view match the start edge of the parent. |
android:layout_alignParentTop | If true, makes the top edge of this view match the top edge of the parent. |
android:layout_alignRight | Makes the right edge of this view match the right edge of the given anchor view ID. |
android:layout_alignStart | Makes the start edge of this view match the start edge of the given anchor view ID. |
android:layout_alignTop | Makes the top edge of this view match the top edge of the given anchor view ID. |
android:layout_alignWithParentIfMissing | If set to true, the parent will be used as the anchor when the anchor cannot be be found for layout_toLeftOf, layout_toRightOf, etc. |
android:layout_below | Positions the top edge of this view below the given anchor view ID. |
android:layout_centerHorizontal | If true, centers this child horizontally within its parent. |
android:layout_centerInParent | If true, centers this child horizontally and vertically within its parent. |
android:layout_centerVertical | If true, centers this child vertically within its parent. |
android:layout_toEndOf | Positions the start edge of this view to the end of the given anchor view ID. |
android:layout_toLeftOf | Positions the right edge of this view to the left of the given anchor view ID. |
android:layout_toRightOf | Positions the left edge of this view to the right of the given anchor view ID. |
android:layout_toStartOf | Positions the end edge of this view to the start of the given anchor view ID. |
示例代码如下:
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/tv_left"
android:text="left"
android:layout_centerInParent="true"
android:layout_toLeftOf="@+id/tv_mid">
</TextView>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="mid"
android:id="@+id/tv_mid"
android:layout_centerInParent="true">
</TextView>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/tv_right"
android:text="right"
android:layout_centerInParent="true"
android:layout_toRightOf="@id/tv_mid">
</TextView>
</RelativeLayout>