当你进入android这个坑的时候,你会发现它是非常复杂,就像Java有JDK一样,Android也有SDK。并且我相信有完整看过Java的所有API的人,那基本上是没有,所以Android也是一样,太多API,太复杂的类继承关系,接口实现关系。
但是我觉得慢慢来,大体了解一下这个体系还是有可能的。因此,学会看google的官方文档那是相当重要(翻墙或者找点国内的某些冒牌网站)。
那就慢慢开始研究吧,一边对照书本看,一边学着看官方文档。
首先书上说了ViewGroup继承了View这个类,并且大部分的布局都是继承了ViewGroup类。那我翻了一下文档,在android.view这个package下发现了View和ViewGroup这两个类,没错你可以发现代码中import也恰好导入了这些东西。然后点击ViewGroup类进去,可以看到它是一个public abstract class,并且extends View,还implements 两个接口,接下来是Known Direct Subclasses(已知的直接继承类),确实有好多Layout,和书中的继承图吻合。
PS:搞android开发,但是毕竟还是Java语言,所以拿Java的语法来解释一切,都必须解释得通!
好吧,以上说了一个参看文档的过程,以后就不详细描述了!
线性布局(LinearLayout)
我们发现很多布局都有android:layout_width和android:layout_height属性,但是我找了很久并没有在LinearLayout中找到相关的xml属性,很显然的想法是可能从父类继承过来的,于是我找了ViewGroup,也并没有发现,仔细看书吧,我发现ViewGroup是有(内部类),找到LayoutParams进去一看,立马发现了上面两个xml属性,这个告诉我们当有时候感觉语法无法解释时,一定要静下心来,想一想到底漏掉了什么地方。可以发现如果思维缜密,还是可以慢慢推理出来的,当然Java功底必须扎实,不然连内部类都不知道,那当然学起来更糊涂!
以上是一些学习心得,以后会穿插讲解。
线性布局是最简单的了,可以认为是我们平常的有一条条横线的笔记本。
这里讲一些常用属性:
orientation表示线性布局内部组件怎么排列,horizontal即为水平排列,但机器不是人,不会因为一行写满而换行,
那vertical是垂直排列,每个组件一行。
layout_gravity,这个应该是LinearLayout特有的,来自于LinearLayout.LayoutParams这个内部类,继承自ViewGroup.MarginLayoutParams,很奇怪内部类继承内部类,这个貌似不太可以,其实外部类必须先继承,这样内部类也就可以访问到了,查了一下源码,发现内部类还是static的。
官方解释:
Standard gravity constant that a child supplies to its parent. Defines how the child view should be positioned, on both the X and Y axes, within its enclosing layout.
翻译一下就是告诉布局组件的位置
Constant | Value | Description |
---|---|---|
top |
0x30 | Push object to the top of its container, not changing its size. |
bottom |
0x50 | Push object to the bottom of its container, not changing its size. |
left |
0x03 | Push object to the left of its container, not changing its size. |
right |
0x05 | Push object to the right of its container, not changing its size. |
center_vertical |
0x10 | Place object in the vertical center of its container, not changing its size. |
fill_vertical |
0x70 | Grow the vertical size of the object if needed so it completely fills its container. |
center_horizontal |
0x01 | Place object in the horizontal center of its container, not changing its size. |
fill_horizontal |
0x07 | Grow the horizontal size of the object if needed so it completely fills its container. |
center |
0x11 | Place the object in the center of its container in both the vertical and horizontal axis, not changing its size. |
fill |
0x77 | Grow the horizontal and vertical size of the object if needed so it completely fills its container. |
clip_vertical |
0x80 | Additional option that can be set to have the top and/or bottom edges of the child clipped to its container's bounds. The clip will be based on the vertical gravity: a top gravity will clip the bottom edge, a bottom gravity will clip the top edge, and neither will clip both edges. |
clip_horizontal |
0x08 | Additional option that can be set to have the left and/or right edges of the child clipped to its container's bounds. The clip will be based on the horizontal gravity: a left gravity will clip the right edge, a right gravity will clip the left edge, and neither will clip both edges. |
start |
0x00800003 | Push object to the beginning of its container, not changing its size. |
end |
0x00800005 | Push object to the end of its container, not changing its size. |
有一堆值,如果要多个就使用位运算或(|),这些值排的挺有意思的,left|right=fill_horizontal,还解释的通...
注意这些常量都在Gravity这个类里
类似的有gravity这个属性,它表示布局控制组件分布的方式,即以布局为视角,而layout_gravity是以组件为视角,两者的取值都可参看上面的表格
做一些测试:
<?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_vertical" >
<Button
android:id="@+id/btn1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="btn1"
/>
</LinearLayout>
gravity表现性能极佳,不管是center_vertical还是center_horizontal,按钮都会显示垂直或水平居中的效果。
<?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" >
<Button
android:id="@+id/btn1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="btn1"
/>
</LinearLayout>
然而这段代码,按钮并不会水平居中,但是如果将center_horizontal改为center_vertical则按钮会水平居中,继续做一下测试
<?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" >
<Button
android:id="@+id/btn1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="btn1"
/>
</LinearLayout>
多加1个垂直方向的orientation,按钮就可以水平居中了。
猜测:layout_gravity与布局的orientation有关,因为一开始没加orientation,默认是horizontal,这样我们发现水平方向对齐方式失效,而垂直方向有效,将orientation修改为vertical后,垂直方向对齐方式失效,水平方向有效。这个不就是说只有对齐方式与orientation垂直的方向有效吗?
本弱无法解释这是为什么,可能是开发人员考虑到某些情况吧,所以强制做了规定哦。
这篇博客讲的挺详细的,传送门:android layout_gravity失效的问题
说了这个确实有一定道理,因为当orientation为horizontal时,那么每行是无限长的,那么right就没有意义了,可能开发人员考虑了这些因素吧...
还有一个属性weight,这个很多人都不理解,其实是需要计算剩余空间的,具体参考:layout_weight
baselineAligned这个当orientation="horizontal"时,如果字体大小不一样,那么将baselineAligned设置为false会有体现,具体参看:baselineAligned
表格布局(TableLayout)
顾名思义:你可以把整个布局想像成一张表格,表格的行数由TableRow的个数决定,表格的列数由每个TableRow中的列数的最大值决定,而TableRow的列数一般是由它所包含的组件的个数。这里注意单独一个组件(不包含在TableRow标签下)独占一行,并且不应该看成表格行数,否则很多现象无法解释。比如表格的每列的宽度,由所有TableRow的对应列的宽度的最大值决定,如果你把独占一行的也看成表格的行,那第0列的宽度就应该是整个屏幕了(注意行和列下标均有0开始)
表格布局的TableRow的layout_weight和layout_height都是默认wrap_content,因此无论你设否设置这两个属性,都是不会起效果的。当你在TableRow里放了一个含有很多文字的组件,这个组件会超出屏幕范围,而不是自动换行,如果要换行,就得考虑使用一些属性。
collapseColumns:隐藏列,如果你想隐藏第1列,那么就设置collapseColumns="0",那么第1列组件全部不会显示,并且原先第2列及以后的列,都会同步左移
shrinkColumns:收缩列,既然要收缩,首先组件得占满屏幕的宽度,比如上面的例子,字很多的组件,超出了屏幕范围,这个时候设置收缩列,那么文字会自动换行,同时组件的高度也会相应增加。
stretchColumns:拉伸列,既然要拉伸,首先组件不可以占满的屏幕的宽度,拉伸值当然是把剩余屏幕宽度填满。
这里给一些参考的博客: TableLayout TableLayout详解
帧布局(FrameLayout)
这个有点类似photoshop中的图层的意思,在FrameLayout中,每个组件占一个图层,先定义的组件占的图层在底部,所以经典案例,可以定义6个不同颜色的正方形的TextView,并且大小逐渐变小,位置设置为居中,由于上层的会覆盖下层的,所以下层只能露出4条边界线,如果在Java代码里我们让这6个TextView不停改变颜色,那么就有霓虹灯的效果了。
布局代码:
<?xml version="1.0" encoding="utf-8" ?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:background="#f00"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:width="320px"
android:height="320px" />
<TextView
android:background="#0f0"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:width="280px"
android:height="280px" />
<TextView
android:background="#00f"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:width="240px"
android:height="240px" />
<TextView
android:background="#ff0"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:width="180px"
android:height="180px" />
<TextView
android:background="#f0f"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:width="140px"
android:height="140px" />
<TextView
android:background="#0ff"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:width="100px"
android:height="100px" />
</FrameLayout>
注意一下:这里的weight和height两个属性,是指组件的大小,并且只有当layout_weight和layout_height为wrap_content时才起效果。
相对布局(RelativeLayout):
控制在父容器中的位置
layout_centerHorizontal: 水平居中
layout_centerVertical:垂直居中
layout_centerInParent:居中
layout_alignParentBottom:底端对齐
layout_alignParentTop:顶端对齐
layout_alignParentLeft:左边对齐
layout_alignParentRight:右边对齐
控制与另一个子组件的位置
layout_toRightOf:在子组件的右侧
layout_toLeftOf:在子组件的左侧
layout_above:在子组件的上方
layout_below:在子组件的下方
layout_alignTop:与子组件的上边界对齐
layout_alginBottom:与子组件的下边界对齐
layout_alginLeft:与子组件的左边界对齐
layout_alginRight:与子组件的右边界对齐
注意:高版本的sdk,有些许变化,Left会被Start替代,Right会被End替代
布局:
<?xml version="1.0" encoding="utf-8" ?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:id="@+id/view01"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/java"
android:layout_centerInParent="true" />
<TextView
android:id="@+id/vie02"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/ee"
android:layout_toStartOf="@id/view01"
android:layout_toLeftOf="@id/view01"
android:layout_alignTop="@id/view01" />
<TextView
android:id="@+id/vie03"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/ee"
android:layout_toEndOf="@id/view01"
android:layout_toRightOf="@id/view01"
android:layout_alignTop="@id/view01" />
<TextView
android:id="@+id/vie04"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/ee"
android:layout_above="@id/view01"
android:layout_alignLeft="@id/view01" />
<TextView
android:id="@+id/vie05"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/ee"
android:layout_below="@id/view01"
android:layout_alignLeft="@id/view01" />
</RelativeLayout>
绝对布局(AbsoluteLayout)
layout_x:X坐标
layout_y:Y坐标
兼容性不强,用的不是很多
未完...