Android的布局

当你进入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坐标

兼容性不强,用的不是很多


未完...





猜你喜欢

转载自blog.csdn.net/u012866104/article/details/50379426