来把常用组件总结一下,方便之后的自定义组件的文章。
先从布局开始。
线性布局,该布局中的组件都是按照垂直或者水平排列。可以通过 android:orentation
这一属性来指定布局方向,该属性有 horizontal - 水平
和 vertical - 垂直
两个值可选。
LinearLayout 还有一个重要的内容是这个布局形式可以使用权重的方式排列组件。使用 android:weight
属性为布局内的组件设置权重。默认是 0。
设置了权重的子组件会按照比例分配父空间中剩余的空间。
例如:
<?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">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#000fff"
android:text="111" />
<TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="2"
android:background="#fff000"
android:text="222" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="3"
android:background="#a0a0a0"
android:text="333" />
</LinearLayout>
显示如下:
来把常用组件总结一下,方便之后的自定义组件的文章。
先从布局开始。
线性布局,该布局中的组件都是按照垂直或者水平排列。可以通过 android:orentation
这一属性来指定布局方向,该属性有 horizontal - 水平
和 vertical - 垂直
两个值可选。
LinearLayout 还有一个重要的内容是这个布局形式可以使用权重的方式排列组件。使用 android:weight
属性为布局内的组件设置权重。默认是 0。
设置了权重的子组件会按照比例分配父空间中剩余的空间。
例如:
<?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">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#000fff"
android:text="111" />
<TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="2"
android:background="#fff000"
android:text="222" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="3"
android:background="#a0a0a0"
android:text="333" />
</LinearLayout>
显示如下:
可以看到,没有设置权限的 111 只是占据文字本身的高度,而 222 的权重是 2,所以它占了剩余部分的 2/5,而 333 权重是 3,所以占了 3/5。
LinearLayout 还有哪些属性可以使用呢?看一下它的官方文档:LinearLayout.LayoutParams
一个例子来展示二者的区别:
<?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:gravity="center"
android:orientation="vertical"
android:layout_margin="20dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="这是一个文本" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:gravity="left"
android:text="start" />
</LinearLayout>
该布局文件效果如下:
文本控件和按钮都在屏幕中间,是因为在 LinearLayout 当中设置了 android:gravity="center"
按钮在中间的右边,是因为按钮控件设置了 android:layout_gravity="right"
,而按钮上的文字是位于按钮的左边,是因为设置了 android:gravity="left"
有两个属性可能会有一些懵逼,layout_marginStart
和 layout_marginEnd
,这两个属性是用来适配哪些从右往左写的语言的(例如阿拉伯语),当系统设置为阿拉伯语时,layout_marginStart
就相当于 layout_marginRight
,这是系统自动实现的。
adnroid:margin
一样。一个例子演示一下 margin 和 padding 的区别:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="50dp"
android:background="#B3EE3A"
android:orientation="vertical"
android:padding="30dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#00C5CD"
android:text="This is a string" />
</LinearLayout>
该布局显示如下:
android:divider
用来指定分割线的样式,可以是一张图片,也可以是 xml 绘制的 shape。android:showDividers
用来指定分割线的位置,有 beginning|middle|end|none 几个值可选。例子:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:divider="@drawable/cutting"
android:gravity="center"
android:showDividers="beginning|middle|end">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#00C5CD"
android:text="This is a string" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#00C5CD"
android:text="This is a string" />
</LinearLayout>
```xml
该布局显示为:
![](https://www.li-xyz.com:1443/content/images/2017/06/2865879473.png)
- android:baselineAligned:该属性是用来设置布局控件中子控件内的文字的基线是否对齐。有 true 和 false 两个值可选,默认为 true。
例子:
```xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:baselineAligned="true|false"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#00C5CD"
android:text="one"
android:textSize="36dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#00C5CD"
android:text="two"
android:textSize="16dp" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="50dp"
android:text="three"/>
</LinearLayout>
显示如下:
更多关于 LinearLayout 的内容,请查看: LinearLayout 和 LinearLayout.LayoutParams.html
和线性布局不同,相对布局是使用“相对位置”来布局子控件的布局。每个子控件的位置可以相对于相邻组件来设置(例如在 xxx 组件的左边、右边),或者相对于父控件区域位置来指定(例如位于布局的底部等)。
常用属性:
该系列的值为 true 或者 false。
示例:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="30dp">
<Button
android:id="@+id/bt0"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="0" />
<Button
android:id="@+id/bt1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:text="1" />
<Button
android:id="@+id/bt2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:text="2" />
<Button
android:id="@+id/bt3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:text="3" />
<Button
android:id="@+id/bt4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:text="4" />
</RelativeLayout>
其效果如下:
这些属性需要使用“@id/xxxx”来引入标准控件的id,并且当一个控件以另外一个控件为标准时,另一个控件一定要定义在这个控件前面,否则会出现找不到id的情况。
实例:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/button3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="Button 3" />
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@id/button3"
android:layout_toLeftOf="@id/button3"
android:text="Button 1" />
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@id/button3"
android:layout_toRightOf="@id/button3"
android:text="Button 2" />
<Button
android:id="@+id/button4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/button3"
android:layout_toLeftOf="@id/button3"
android:text="Button 4" />
<Button
android:id="@+id/button5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/button3"
android:layout_toRightOf="@id/button3"
android:text="Button 5" />
</RelativeLayout>
该布局显示如下:
框架布局没有任何定位方式,帧布局容器每加入一个组件创建一个空白区域,每个组件占据一帧,添加的组件是一个一个叠在一起的,默认位置是左上角。
示例:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/firstView"
android:text="第一层"
android:textSize="50sp"
android:textColor="#000000"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/secondView"
android:text="第二层"
android:textSize="30sp"
android:textColor="#ffff00"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/thirdView"
android:text="第三层"
android:textSize="15sp"
android:textColor="#ff00ff"/>
</FrameLayout>
该布局显示如下:
难道真的是FrameLayout中的子元素完全无法控制自身在布局中的位置吗?其实不是的,android:laytou_gravity属性可以改编控件在布局中的位置
如下:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/firstView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="第一层"
android:textColor="#000000"
android:textSize="50sp" />
<TextView
android:id="@+id/secondView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="第二层"
android:textColor="#ffff00"
android:textSize="30sp" />
<TextView
android:id="@+id/thirdView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:text="第三层"
android:textColor="#ff00ff"
android:textSize="15sp" />
</FrameLayout>
该布局显示如下:
该布局还有两个个重要属性:
示例:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:foreground="@mipmap/ic_launcher"
android:foregroundGravity="bottom|left">
<TextView
android:id="@+id/firstView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="第一层"
android:textColor="#000000"
android:textSize="50sp" />
<TextView
android:id="@+id/secondView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="第二层"
android:textColor="#ffff00"
android:textSize="30sp" />
<TextView
android:id="@+id/thirdView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:text="第三层"
android:textColor="#ff00ff"
android:textSize="15sp" />
</FrameLayout>
该布局显示如下:
TableLayout 运行我们使用表格的方式来排列控件,它的本质依然是线性布局。表格布局采用行、列的形式来管理控件,TableLayout 并不需要明确的声明包含多少行多少列,而是通过添加 TableRow、其他组件来控制表格的行数和列数。
每次向 Table 中添加一个 TableRow,该 TableRow 就是一个表格行,TableRow 也是容器,因此它也可以不断的添加其他组件,每添加一个子组件该表格就增加一列。
例如:
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="30dp"
android:stretchColumns="1">
<TableRow>
<TextView
android:layout_height="wrap_content"
android:text="账户:" />
<EditText
android:id="@+id/usernameInput"
android:layout_height="wrap_content"
android:hint="输入要注册的用户名" />
</TableRow>
<TableRow>
<TextView
android:layout_height="wrap_content"
android:text="密码:" />
<EditText
android:id="@+id/passwordInput"
android:layout_height="wrap_content"
android:hint="输入要密码"
android:inputType="textPassword" />
</TableRow>
<TableRow>
<Button
android:id="@+id/loginButton"
android:layout_height="wrap_content"
android:layout_span="2"
android:text="登录" />
</TableRow>
</TableLayout>
该布局演示如下:
该布局有以下几个重要属性:
网格布局是 Android4.0 新增的布局管理器,因此需要在 Android4.0 之后的版本才可以使用,之前的平台使用该布局的话,需要导入相应的支持库。
GridLayout 的作用类似于 HTML 中的 table 标签,它把整个容器划分成 row*column 个网格,每个网格都可以放置一个组件,也可以设置一个组件横跨多少列、多少行。
GridLayout 提供了 setRowCount(int) 和 setColumnCount(int) 方法来控制该网格的行数和列数。
<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:rowCount="6"
android:columnCount="4"
android:id="@+id/root">
<!-- 定一个一个横跨四列的文本框,并设置该文本框的前景色、背景色等属性 -->
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_columnSpan="4"
android:textSize="50sp"
android:layout_marginLeft="4px"
android:layout_marginRight="4px"
android:padding="5px"
android:layout_gravity="right"
android:background="#eee"
android:textColor="#000"
android:text="0"
/>
<!-- 定义一个横跨四列的按钮 -->
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_columnSpan="4"
android:text="清除"/>
<!-- 添加其他按钮 -->
<Button
android:text="7"
android:layout_rowWeight="1"
android:layout_columnWeight="1"/>
<Button
android:text="8"
android:layout_rowWeight="1"
android:layout_columnWeight="1"/>
<Button
android:text="9"
android:layout_rowWeight="1"
android:layout_columnWeight="1"/>
<Button
android:text="/"
android:layout_rowWeight="1"
android:layout_columnWeight="1"/>
<Button
android:text="4"
android:layout_rowWeight="1"
android:layout_columnWeight="1"/>
<Button
android:text="5"
android:layout_rowWeight="1"
android:layout_columnWeight="1"/>
<Button
android:text="6"
android:layout_rowWeight="1"
android:layout_columnWeight="1"/>
<Button
android:text="*"
android:layout_rowWeight="1"
android:layout_columnWeight="1"/>
<Button
android:text="1"
android:layout_rowWeight="1"
android:layout_columnWeight="1"/>
<Button
android:text="2"
android:layout_rowWeight="1"
android:layout_columnWeight="1"/>
<Button
android:text="3"
android:layout_rowWeight="1"
android:layout_columnWeight="1"/>
<Button
android:text="-"
android:layout_rowWeight="1"
android:layout_columnWeight="1"/>
<Button
android:text="0"
android:layout_rowWeight="1"
android:layout_columnWeight="1"/>
<Button
android:text="."
android:layout_rowWeight="1"
android:layout_columnWeight="1"/>
<Button
android:text="+"
android:layout_rowWeight="1"
android:layout_columnWeight="1"/>
<Button
android:text="="
android:layout_rowWeight="1"
android:layout_columnWeight="1"/>
</GridLayout>
该布局显示如下:
该布局有以下几个属性:
依赖布局是 Google I/O 2016 上发布的,大概看了一下,感觉这个布局的出现,更适合把界面设计工作交给设计师来操作,设计师不需要懂代码,直接拖曳控件就好,对于程序员来说,似乎并不是很实用,因为代码量似乎变得多了。。。
有人总结了很好的文章,可以看这里:
这个严格意义上讲并不是一个布局,它提供了两个“布局”,在这两个布局中,我们可以使用百分比来确定组件的大小位置,是不是很棒?
使用该库,需要引入依赖:compile 'com.android.support:percent:22.2.0'
该库提供了两个类:PercentFrameLayout 和 PercentRelativeLayout,顾名思义,就是 FrameLayout 和 RelativeLayout 的延伸了。
PercentFrameLayout 支持以下属性:
layout_widthPercent:用百分比的形式设置组件宽度
layout_heightPercent:用百分比的形式设置组件高度
layout_marginPercent:用百分比的形式设置 margin
layout_marginLeftPercent:用百分比的形式设置 marginLeft
layout_marginTopPercent:用百分比的形式设置 marginTop
layout_marginRightPercent:用百分比的形式设置 marginRight
layout_marginBottomPercent:用百分比的形式设置 marginBottom
layout_marginStartPercent:用百分比的形式设置 marginStart
layout_marginEndPercent:用百分比的形式设置 marginEnd
layout_aspectRatio:通过只设置width或者height和layout_aspectRatio这种比例值的方式来让第另一个值自动计算。
例子:
<android.support.percent.PercentFrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:background="#fff000"
android:text="1"
app:layout_heightPercent="20%"
app:layout_marginLeftPercent="50%"
app:layout_widthPercent="10%" />
<Button
android:layout_width="100dp"
android:background="#00BFFF"
android:text="2"
app:layout_aspectRatio="200%" />
<Button
android:layout_width="100dp"
android:background="#40E0D0"
android:text="3"
app:layout_aspectRatio="100%"
app:layout_marginTopPercent="50%" />
</android.support.percent.PercentFrameLayout>
该布局显示如下:
PercentRelativeLayout 可以使用的属性也和 PercentFrameLayout 一样,例子就不举了。
更多参考:
有时候我们的布局会非常复杂,如果还是直接简单粗暴的堆积组件,那么系统在绘制布局的时候会相对的耗时耗力,这个时候布局优化就显得特别重要了。布局优化主要有以下几点:
举个例子来看一下:
我们要实现以下布局:
使用 LinearLayout
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="10dp">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/ic_launcher" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="使用 LinearLayout" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="使用 LinearLayout" />
</LinearLayout>
</LinearLayout>
可以看到,使用 LinearLayout 来实现这个布局,会有两层:
使用 RelativeLayout
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="10dp">
<ImageView
android:id="@+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/ic_launcher" />
<TextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:layout_toRightOf="@id/image"
android:text="使用 RelativeLayout" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/text"
android:layout_marginTop="5dp"
android:layout_toRightOf="@id/image"
android:text="使用 RelativeLayout" />
</RelativeLayout>
使用 RelativeLayout 来实现,就会只有一层:
层级减少了,渲染的时间自然也就减少了。
<include>
标签<include>
标签来引入这个公共的组件。
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<ImageView
android:id="@+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/ic_launcher" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
android:layout_toRightOf="@id/image"
android:text="AppName" />
</RelativeLayout>
然后在我们的布局中引入这个布局
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="10dp">
<include
android:id="@+id/title"
layout="@layout/title_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/textView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/title"
android:text="111111111111111111111111111111" />
</RelativeLayout>
最后显示如下:
<merge>
标签<merge>
标签在你嵌套 Layout 时取消了 UI 层级中冗余的 ViewGroup。比如,如果你有一个 Layout 是一个竖直方向的 LinearLayout,其中包含两个连续的 View 可以在别的 Layout 中重用,那么你会做一个 LinearLayout 来包含这两个 View,以便重用。不过,当使用一个 LinearLayout 作为另一个 LinearLayout 的根节点时,这种嵌套 LinearLayout 的方式除了减慢你的 UI 性能外没有任何意义。<merge>
元素来替代可重用 Layout 的根节点。例如:<merge xmlns:android="http://schemas.android.com/apk/res/android">
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/add"/>
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/delete"/>
</merge>
现在,当你要将这个 Layout 包含到另一个 Layout 中时(并且使用了 <include>
标签),系统会忽略 <merge>
标签,直接把两个 Button 放到 Layout 中 <include>
的所在位置。