布局管理器是以ViewGroup派生而来的
所有布局都可作为容器类使用,因此可以调用多个重载的addView()向布局管理器中添加组件。(实际上可以将一个布局管理器嵌套在另一个布局管理器中)
2.2.1 线性布局 LinearLayout
容器里的组件会一个挨着一个地排列。可以横向排列,亦可以纵向排列
Android的线性布局不会换行,当组件一个挨着一个地排列到头后,剩下的组件将不会显示
LinearLayout支持的常用XML属性:
android:baselineAligned
|
|
该属性设置为false,将会阻止该布局管理器与它的子元素基线对齐
|
android:divider
|
|
设置垂直布局时两个按钮之间的分隔条
|
android:gravity
|
|
设置布局管理器内组件的对齐方式。支持top、bottom\right\center_vertical\fill_vertical\center_horizontal\fill_horizontal\center\fill\clip_vertical\clip_horizontal几个属性值。也可同时指定多种对齐方式;如left|center_vertical代表出现在屏幕左边,而且垂直居中
|
android:measureWithLargestChild
|
|
当该属性值设为true时,所有带权重的子元素都会有最大子元素的最小尺寸
|
android:orientation
|
|
设置布局管理器内组件的排列方式,可以设置为horizontal、vertical两个值之一
|
LinearLayout包含的所有子元素都受LinearLayout.LayoutParams控制,因此LinearLayout包含的子元素可以额外指定如下xml属性
android:layout_gravity
|
对齐方式
|
android:layout_weight
|
在LinearLayout中所占权重
|
实例代码:XML布局文件
<
LinearLayout
xmlns:android
=
"http://schemas.android.com/apk/res/android"
android:orientation = "vertical"
android:layout_width = "fill_parent"
android:layout_height = "fill_parent"
android:gravity = "top|center_horizontal"
>
< Button
android:id = "@+id/bn1"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "@string/bn1"
/>
< Button
android:id = "@+id/bn2"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "@string/bn2"
/>
< Button
android:id = "@+id/bn3"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "@string/bn3"
/>
< Button
android:id = "@+id/bn4"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "@string/bn4"
/>
< Button
android:id = "@+id/bn5"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "@string/bn5"
/>
android:orientation = "vertical"
android:layout_width = "fill_parent"
android:layout_height = "fill_parent"
android:gravity = "top|center_horizontal"
>
< Button
android:id = "@+id/bn1"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "@string/bn1"
/>
< Button
android:id = "@+id/bn2"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "@string/bn2"
/>
< Button
android:id = "@+id/bn3"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "@string/bn3"
/>
< Button
android:id = "@+id/bn4"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "@string/bn4"
/>
< Button
android:id = "@+id/bn5"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "@string/bn5"
/>
</
LinearLayout
>
2.2.2 表格布局 TableLayout
TableLayout继承了LinearLayout,因此它本质上依然是线性布局管理器。采用行、列的形式来管理UI组件,TableLayout并不需要明确声明包含多少行、多少列,而是通过添加TableRow、其他组件来控制表格的行数和列数。
每向TableLayout中添加一个TableRow,该TableRow就是一个表格行,TableRow也是容器,也可不断地向其添加组件,每添加一个子组件该表格行就增加一列。(若直接想TableLayout中添加组件,那么这个组件将直接占用一行)
在表格布局管理器中,可以为单元格设置如下三种行为:
Shrinkable:可收缩,以适应父容器的宽度
Stretchable:可拉伸,以保证组件能够完全填满表格空余空间
Collapsed:若某列被设置为Collapsed,那么该列的所有单元格会被隐藏。
TableLayout继承了LinearLayout,因此它完全支持LinearLayout所有支持的XML属性,此外它还支持如下XML属性:
android:collapseColumns
|
|
设置需要被隐藏的列的列序号,多个列序号以逗号隔开
|
android:shrinkColumns
|
|
允许被收缩的列序号,多个。。。。
|
android:stretchColumns
|
|
允许被拉伸的列序号,多个。。。。
|
表格布局示例程序:
activity_main.xml
<
LinearLayout
xmlns:android
=
"http://schemas.android.com/apk/res/android"
android:orientation = "vertical"
android:layout_width = "fill_parent"
android:layout_height = "fill_parent"
>
< TableLayout android:id = "@+id/TableLayout01"
android:layout_width = "fill_parent"
android:layout_height = "wrap_content"
android:shrinkColumns = "1"
android:stretchColumns = "2"
>
< Button android:id = "@+id/ok1"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "独自一行的按钮"
/>
< TableRow >
< Button android:id = "@+id/ok2"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "普通按钮"
/>
< Button android:id = "@+id/ok3"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "收缩的按钮"
/>
< Button android:id = "@+id/ok4"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "拉伸的按钮"
/>
</ TableRow >
</ TableLayout >
< TableLayout android:id = "@+id/TableLayout02"
android:layout_width = "fill_parent"
android:layout_height = "wrap_content"
android:collapseColumns = "1"
>
< Button android:id = "@+id/ok5"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "独自一行的按钮"
/>
< TableRow >
< Button android:id = "@+id/ok6"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "普通按钮"
/>
< Button android:id = "@+id/ok7"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "收缩的按钮"
/>
< Button android:id = "@+id/ok8"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "拉伸的按钮"
/>
</ TableRow >
</ TableLayout >
< TableLayout android:id = "@+id/TableLayout03"
android:layout_width = "fill_parent"
android:layout_height = "wrap_content"
android:stretchColumns = "1,2"
>
< Button android:id = "@+id/ok9"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "独自一行的按钮"
/>
< TableRow >
< Button android:id = "@+id/ok10"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "普通按钮"
/>
< Button android:id = "@+id/ok11"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "收缩的按钮"
/>
< Button android:id = "@+id/ok12"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "拉伸的按钮"
/>
</ TableRow >
< TableRow >
< Button android:id = "@+id/ok13"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "收缩的按钮"
/>
< Button android:id = "@+id/ok14"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "拉伸的按钮"
/>
</ TableRow >
</ TableLayout >
android:orientation = "vertical"
android:layout_width = "fill_parent"
android:layout_height = "fill_parent"
>
< TableLayout android:id = "@+id/TableLayout01"
android:layout_width = "fill_parent"
android:layout_height = "wrap_content"
android:shrinkColumns = "1"
android:stretchColumns = "2"
>
< Button android:id = "@+id/ok1"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "独自一行的按钮"
/>
< TableRow >
< Button android:id = "@+id/ok2"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "普通按钮"
/>
< Button android:id = "@+id/ok3"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "收缩的按钮"
/>
< Button android:id = "@+id/ok4"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "拉伸的按钮"
/>
</ TableRow >
</ TableLayout >
< TableLayout android:id = "@+id/TableLayout02"
android:layout_width = "fill_parent"
android:layout_height = "wrap_content"
android:collapseColumns = "1"
>
< Button android:id = "@+id/ok5"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "独自一行的按钮"
/>
< TableRow >
< Button android:id = "@+id/ok6"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "普通按钮"
/>
< Button android:id = "@+id/ok7"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "收缩的按钮"
/>
< Button android:id = "@+id/ok8"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "拉伸的按钮"
/>
</ TableRow >
</ TableLayout >
< TableLayout android:id = "@+id/TableLayout03"
android:layout_width = "fill_parent"
android:layout_height = "wrap_content"
android:stretchColumns = "1,2"
>
< Button android:id = "@+id/ok9"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "独自一行的按钮"
/>
< TableRow >
< Button android:id = "@+id/ok10"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "普通按钮"
/>
< Button android:id = "@+id/ok11"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "收缩的按钮"
/>
< Button android:id = "@+id/ok12"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "拉伸的按钮"
/>
</ TableRow >
< TableRow >
< Button android:id = "@+id/ok13"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "收缩的按钮"
/>
< Button android:id = "@+id/ok14"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "拉伸的按钮"
/>
</ TableRow >
</ TableLayout >
</
LinearLayout
>
2.2.3 帧布局 FrameLayout
FrameLayout 直接继承了ViewGroup组件。
帧布局容器为每个加入其中的组件创建一个空白的区域,每个子组件占据一个帧,这些帧都会根据gravity属性执行自动对齐。
FrameLayout常用XML属性:
android:foreground
|
|
设置该帧布局容器的前景图像
|
android:foregroundGravity
|
|
定义绘制前景图像的gravity属性
|
FrameLayout包含的子元素也受FrameLayout.LayoutParams控制,因此它所包含的子元素也可指定android:layout_gravity属性,该属性控制子元素在FrameLayout中的对齐方式
附注: R.color的用法
Android中使用4个数字来表示颜色,分别是alpha、红(red)、绿(green)、蓝(blue)四个颜色值(ARGB)。每个数字取值0-255,因此一个颜色可以用一个整数来表示。为了运行效率,Android编码时用整数Color类实例来表示颜色。
红、绿、蓝三个值是就是代表颜色的取值,而Alpha代表的是透明度。最低值为0,表示颜色完全透明,而此时RGB是什么取值都不重要了。Alpha最高可取值为255,表示颜色完全不透明。如果需要颜色透明、半透明,那么可以取值0-255中间的一些值,这常常用在前端图层绘制时。
有下面几种方式来创建或表示一个颜色:
1、
使用Color类的常量,如:
Int color = Color.BULE;
// 创建一个蓝色
2、
如果知道ARGB的取值,那么可以使用Color类的静态方法argb创建一个颜色:
Int color = Color.argb(127,255,0,255);// 半透明的紫色
3、
使用XML资源文件来表示颜色。这是一个扩展性比较好的方式,便于今后可以方便的修改颜色值。
<?xml version=”1.0” encoding=”utf-8”>
<resources>
<color name=”mycolor”>#7fff00ff</color>
</resources>
定义了一个名为mycolor颜色,在别的地方就可以引用mycolor来获取该颜色值。可以使用ResourceManager类中的getColor来获取该颜色。Java样例代码如下:
Int color = getResources().getColor(R.color.mycolor);
这与第二种方法得到的值是一样的。getResources()方法返回当前活动Activity的ResourceManager类实例。
霓虹灯示例程序:
public
class
MainActivity
extends
ActionBarActivity {
private int currentColor = 0;
final int [] colors = new int []{
R.color. color1 ,
R.color. color2 ,
R.color. color3 ,
R.color. color4 ,
R.color. color5 ,
R.color. color6
};
final int [] names = new int []{
R.id. view01 ,
R.id. view02 ,
R.id. view03 ,
R.id. view04 ,
R.id. view05 ,
R.id. view06 ,
};
TextView[] views = new TextView[ names . length ];
Handler handler = new Handler()
{
@Override
public void handleMessage(Message msg)
{
if (msg. what == 0x123)
{
for ( int i = 0; i < names . length ; i++)
{
views [i].setBackgroundResource( colors [(i
+ currentColor ) % names . length ]);
}
currentColor ++;
}
super .handleMessage(msg);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super .onCreate(savedInstanceState);
setContentView(R.layout. activity_main );
for ( int i = 0; i< names . length ; i++)
{
views [i] = (TextView) findViewById( names [i]);
}
new Timer().schedule( new TimerTask()
{
@Override
public void run()
{
handler .sendEmptyMessage(0x123);
}
},0,500);
private int currentColor = 0;
final int [] colors = new int []{
R.color. color1 ,
R.color. color2 ,
R.color. color3 ,
R.color. color4 ,
R.color. color5 ,
R.color. color6
};
final int [] names = new int []{
R.id. view01 ,
R.id. view02 ,
R.id. view03 ,
R.id. view04 ,
R.id. view05 ,
R.id. view06 ,
};
TextView[] views = new TextView[ names . length ];
Handler handler = new Handler()
{
@Override
public void handleMessage(Message msg)
{
if (msg. what == 0x123)
{
for ( int i = 0; i < names . length ; i++)
{
views [i].setBackgroundResource( colors [(i
+ currentColor ) % names . length ]);
}
currentColor ++;
}
super .handleMessage(msg);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super .onCreate(savedInstanceState);
setContentView(R.layout. activity_main );
for ( int i = 0; i< names . length ; i++)
{
views [i] = (TextView) findViewById( names [i]);
}
new Timer().schedule( new TimerTask()
{
@Override
public void run()
{
handler .sendEmptyMessage(0x123);
}
},0,500);
}
}
为何不直接在run()方法里直接更新6个TextView的背景颜色呢?
这是因为Android的View和UI组件不是线程安全的,所以Android不允许开发者启动线程访问用户界面的UI组件
2.2.4 相对布局
RelativeLayout
相对布局容器内子组件的位置总是相对兄弟组件、父容器来决定的,因此这种布局方式被称为相对布局。
在相对布局中,Android要求先定义被依赖组件;
RelativeLayout 可支持如下XML属性:
android:gravity
|
|
该布局容器内各子组件的对齐方式
|
android:ignoreGravity
|
|
设置哪个组件不受gravity属性的影响
|
为了控制该布局容器中各子组件的布局分布,RelativeLayout提供了一个内部类:RelativeLayout.LayoutParams,该类提供了大量的xml属性来控制RelativeLayout布局容器中子组件的布局分布
其中,只能设置为true、false的xml属性如下表:
android:layout_centerHorizontal
|
水平居中
|
android:layout_centerVertical
|
垂直居中
|
android:layout_centerInParent
|
中央位置
|
android:layout_alignParentBottom
|
与布局容器底端对齐
|
android:layout_alignParentLeft
|
与布局容器左边对齐
|
android:layout_alignParentRight
|
|
android:layout_alignParentTop
|
|
RelativeLayout.LayoutParams里属性值为其他UI组件ID的XML属性如下表:
android:layout_toRightOf
|
位于给出ID组件的右侧
|
android:layout_toLeftOf
|
|
android:layout_above
|
上方
|
android:layout_below
|
|
android:layout_alignTop
|
与上边界对齐
|
android:layout_alignBottom
|
|
android:layout_alignLeft
|
|
android:layout_alignRight
|
|
RelativeLayout布局容器中每个子组件也可指定android.view.ViewGroup.MarginLayoutParams所支持的各xml属性
2.2.5 Android 4.0 新增的网格布局
GridLayout
GridLayout 把整个容器划分成rows*columns个网格,每个网格可以放置一个组件。此外也可设置一个组件横跨多少列、一个组件横跨多少行。
GridLayout提供了setRowCount(int) 和 setColumnCount(int)方法来控制网格的行数量和列数量
下表列出了GridLayout 常用的xml属性及相关方法说明
android:alignmentMode
|
int
|
设置其采用的对齐模式
|
android:columnCount
|
int
|
设置列数量
|
android:columnOrderPreserved
|
boolean
|
是否保留列序号
|
android:rowCount
| int |
设置行数量
|
android:rowOrderPreserved
|
boolean
|
是否保留行序号
|
android:useDefaultMargins
|
boolean
|
是否使用默认页边距
|
GridLayout提供了一个内部类:GridLayout.LayoutParams,此内部类的xml属性如下表
android:layout_column
|
|
设置该子组件在GridLayout的第几列
|
android:layout_columnSpan
|
|
设置该子组件在GridLayout横向上跨几列
|
android:layout_gravity
|
|
设置该子组件采用何种方式占据该网格空间
|
android:layout_row
|
|
设置该子组件在GridLayout的第几行
|
android:layout_rowSpan
|
|
设置该子组件在GridLayout纵向上跨几行
|
GridLayout示例代码:
xml
<
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 = "Clear"
/>
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 = "Clear"
/>
</
GridLayout
>
activity_main.java
public
class
MainActivity
extends
ActionBarActivity {
GridLayout gridLayout ;
String[] chars = new String[]{
"7" , "8" , "9" , "/" ,
"4" , "5" , "6" , "*" ,
"1" , "2" , "3" , "-" ,
"." , "0" , "=" , "+"
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super .onCreate(savedInstanceState);
setContentView(R.layout. activity_main );
gridLayout = (GridLayout) findViewById(R.id. root );
for ( int i = 0; i < chars . length ; i++)
{
Button bn = new Button( this );
bn.setText( chars [i]);
bn.setTextSize(60);
GridLayout.Spec rowSpec = GridLayout.spec(i/4 + 2);
GridLayout.Spec columnSpec = GridLayout.spec(i % 4);
GridLayout.LayoutParams params = new GridLayout.LayoutParams(rowSpec, columnSpec);
params.setGravity(Gravity. AXIS_PULL_AFTER );
gridLayout .addView(bn, params);
}
GridLayout gridLayout ;
String[] chars = new String[]{
"7" , "8" , "9" , "/" ,
"4" , "5" , "6" , "*" ,
"1" , "2" , "3" , "-" ,
"." , "0" , "=" , "+"
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super .onCreate(savedInstanceState);
setContentView(R.layout. activity_main );
gridLayout = (GridLayout) findViewById(R.id. root );
for ( int i = 0; i < chars . length ; i++)
{
Button bn = new Button( this );
bn.setText( chars [i]);
bn.setTextSize(60);
GridLayout.Spec rowSpec = GridLayout.spec(i/4 + 2);
GridLayout.Spec columnSpec = GridLayout.spec(i % 4);
GridLayout.LayoutParams params = new GridLayout.LayoutParams(rowSpec, columnSpec);
params.setGravity(Gravity. AXIS_PULL_AFTER );
gridLayout .addView(bn, params);
}
}
}
2.2.6 绝对布局 AbsoluteLayout
由开发人员通过X坐标、Y坐标来控制组件的位置,并且子组件的位置、大小也都需要开发人员自己控制
绝大部分时候都不使用绝对布局
XML属性:
layout_x
layout_y