在XML布局文件里,会遇到如下一些单位
px:是屏幕的像素点
in:英寸
mm:毫米
pt:磅,1/72 英寸
dp:一个基于density的抽象单位,如果一个160dpi的屏幕,1dp=1px
dip:等同于dp
sp:同dp相似,但还会根据用户的字体大小偏好来缩放。
建议使用sp作为文本的单位,其它用dip
一.LinearLayout线性布局
线性布局是程序中最常见的一种布局方式,线性布局可以分为水平线性布局和垂直线性布局两种, 通过android:orientation属性可以设置线性布局的方式。
android:orientation:布局中组件的排列方式,有horizontal(水平),vertical(竖直,默认),两种方式
android:gravity:控制组件所包含的子元素的对其方式,可通过时组合多种对其方式:left|buttom
android:layout_gravity:控制该组件在父容器里的对其方式
android:layout_width:布局的宽度,通常不直接写数字的,用wrap_content(组件实际大小), fill_parent或者match_parent填满父容器
android:layout_height:布局的高度,参数同上
android:id:为该组件设置一个资源id,在java文件中可以通过findViewById(id)找到该组件
android:background:为该组件设置一个背景图片,或者直接用颜色覆盖
PS: 1.在LinearLayout中设置排列方式为水平时只有垂直方向的设置是有效的,水平方向的设置是无效的:即left,right,center_horizontal 是不生效的
2.在LinearLayout中设置排列方式为垂直时只有水平方向设置是有效的,垂直方向的设置是无效的是无效的:即top,bottom,center_vertical 是无效的;
<span style="font-family:Times New Roman;font-size:18px;"><span style="font-family:Times New Roman;font-size:18px;">public class LinearLayoutTest extends Activity
{
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}</span></span>
<span style="font-family:Times New Roman;font-size:18px;"><span style="font-family:Times New Roman;font-size:18px;"><?xml version="1.0" encoding="utf-8"?>
<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="center"
>
<Button
android:id="@+id/bn1"
android:layout_width="100dip"
android:layout_height="50dip"
android:background="#ffff00"
android:text="@string/bn1"
android:textColor="#000000"
/>
<Button
android:id="@+id/bn2"
android:layout_width="100dip"
android:layout_height="50dip"
android:background="#ff0000"
android:text="@string/bn2"
android:textColor="#000000"
/>
<Button
android:id="@+id/bn3"
android:layout_width="100dip"
android:layout_height="50dip"
android:background="#66ff00"
android:text="@string/bn3"
android:textColor="#000000"
/>
</LinearLayout>
</span></span>
<span style="font-family:Times New Roman;font-size:18px;"><span style="font-family:Times New Roman;font-size:18px;"><?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="bn1">测试按钮1</string>
<string name="bn2">测试按钮2</string>
<string name="bn3">测试按钮3</string>
<string name="app_name">线性布局</string>
</resources>
</span></span>
二、表格布局
TableLayout跟TableLayout 是一组搭配使用的布局,TableLayout置底,TableRow在TableLayout的上面,而Button、TextView等控件就在TableRow之上,另外,TableLayout之上也可以单独放控件。TableLayout是一个使用复杂的布局,最简单的用法就仅仅是拖拉控件做出个界面,但实际上,会经常在代码里使用TableLayout,例如做出表格的效果。本文主要介绍TableLayout的基本使用方法。
注意:
!!!!!!!!序号是从0开始的,可以同时设置多个列,用逗号","分隔即可
TableLayout经常用的属性是:
TableLayout可设置的属性包括全局属性及单元格属性。
1、全局属性也即列属性,有以下3个参数:
android:stretchColumns 设置可伸展的列。该列可以向行方向伸展,最多可占据一整行。
android:shrinkColumns 设置可收缩的列。当该列子控件的内容太多,已经挤满所在行,那么该子控件的内容将往列方向显示。
android:collapseColumns 设置要隐藏的列。
示例:
android:stretchColumns="0" 第0列可伸展
android:shrinkColumns="1,2" 第1,2列皆可收缩
android:collapseColumns="*" 隐藏所有行
说明:列可以同时具备stretchColumns及shrinkColumns属性,若此,那么当该列的内容N多时,将“多行”显示其内容。(这里不是真正的多行,而是系统根据需要自动调节该行的layout_height)
2、单元格属性,有以下2个参数:
android:layout_column 指定该单元格在第几列显示
android:layout_span 指定该单元格占据的列数(未指定时,为1)
<span style="font-family:Times New Roman;font-size:18px;"><span style="font-family:Times New Roman;font-size:18px;">public class TableLayoutTest extends Activity
{
// 当第一次创建该Activity时回调该方法
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}</span></span>
<span style="font-family:Times New Roman;font-size:18px;"><span style="font-family:Times New Roman;font-size:18px;"><?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<!-- 定义第一个表格布局,指定第2列允许收缩,第3列允许拉伸 -->
<TableLayout android:id="@+id/TableLayout01"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#ffff33"
android:shrinkColumns="1"
android:stretchColumns="2"
>
<!-- 直接添加按钮,它自己会占一行 -->
<Button android:id="@+id/ok1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="独自一行的按钮"
/>
<!-- 添加一个表格行 -->
<TableRow>
<!-- 为该表格行添加3个按钮 -->
<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:background="#99ff00"
android:collapseColumns="1"
>
<!-- 直接添加按钮,它自己会占一行 -->
<Button android:id="@+id/ok5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=" 独自一行的按钮 "
/>
<!--定义一个表格行-->
<TableRow>
<!-- 为该表格行添加3个按钮 -->
<Button android:id="@+id/ok6"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="普通按钮1"
/>
<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="普通按钮 3"
/>
</TableRow>
</TableLayout>
<!-- 定义第三个表格布局 ,指定第2、3两列可以被拉伸-->
<TableLayout android:id="@+id/TableLayout03"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#00cccc"
android:stretchColumns="1,2"
>
<!-- 直接添加按钮,它自己会占一行 -->
<Button android:id="@+id/ok9"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="独自一行的按钮"
/>
<!--定义一个表格行-->
<TableRow>
<!-- 为该表格行添加3个按钮 -->
<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>
<!-- 为该表格行添加2个按钮 -->
<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></span></span>
<span style="font-family:Times New Roman;font-size:18px;"><span style="font-family:Times New Roman;font-size:18px;"><?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="hello">Hello World, TableLayoutTest!</string>
<string name="app_name">表格布局</string>
</resources>
</span></span>
三、帧布局
android中贞布局由FrameLayout所代表,FrameLayout直接继承了 ViewGroup 组件。
帧布局容器为每个加入其中的组件创建一个空白的区域 (称为一帧),所有每个子组件占据一帧,这些帧都会根据 gravity属性执行自动对齐。也就是说,巾贞布局的效果有点类似 于AWT编程的CardLayout,都是把组件一个一个地叠加在一 起。与CardLayout的区别在于,CardLayout可以将下面的Card 移上来,但FrameLayout则没有提供相应的方法。
表2.6显示了 FmmeLayout常用的XML属性及相关方法说明。
表2.6 FrameLayout的常用XML属性及相关方法
XML属性 相关方法 说 明
android:foreground setForcground(Drawablc) 设迓该帧布局容器的前联图像
android: foregroundGravity setForegroundGravity(int) 定义绘制前眾阁像的gravity M性
<span style="font-family:Times New Roman;font-size:18px;"><span style="font-family:Times New Roman;font-size:18px;">public class FrameLayoutTest extends Activity
{
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
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
for (int i = 0; i < names.length; i++)
{
views[i] = (TextView) findViewById(names[i]);
}
// 定义一个线程周期性的改变currentColor变量值
new Timer().schedule(new TimerTask()
{
@Override
public void run()
{
// 发送一条空消息通知系统改变6个TextView组件的背景色
handler.sendEmptyMessage(0x123);
}
}, 0, 200);
}
}</span></span>
四、相对布局
相对布局是android布局中最为强大的,首先它可以设置的属性是最多了,其次它可以做的事情也是最多的。android手机屏幕的分辨率五花八门所以为了考虑屏幕自适应的情况所以在开发中建议大家都去使用相对布局 它的坐标取值范围都是相对的所以使用它来做自适应屏幕是正确的
设置布局里面所有组件的对其方式:
android:gravity:设置容器内各个子组件的对齐方式
android:ignoreGravity:如果为哪个组件设置了这个属性的话,那么该组件不受gravity属性的影响
根据父容器来定位:
想位于哪,哪个属性就设置为true
左对齐:android:layout_alighParentLeft
右对齐:android:layout_alighParentRight
顶端对齐:android:layout_alighParentTop
底部对齐:android:layout_alighParentBottom
水平居中:android:layout_centerHorizontal
垂直居中:android:layout_centerVertical
中央位置:android:layout_centerInParent
根据兄弟组件来定位:
右面的属性值为兄弟组件的id
左边:android:layout_toLeftOf
右边:android:layout_toRightOf
上方:android:layout_above
下方:android:layout_below
对齐上边界:android:layout_alignTop
对齐下边界:android:layout_alignBottom
对齐左边界:android:layout_alignLeft
对齐右边界:android:layout_alignRight
在进行相对布局时用到的属性很多,首先来看属性值只为true 或false 的属性,如表1-1所示。
表1-1 相对布局中只取true 或false 的属性及说明
属性名称 | 属性说明 |
android:layout_centerHorizontal | 当前控件位于父控件的横向中间位置 |
android:layout_centerVertical | 当前控件位于父控件的纵向中间位置 |
android:layout_centerInParent | 当前控件位于父控件的中央位置 |
android:layout_alignParentBottom | 当前控件底端与父控件底端对齐 |
接下来看属性值为其他控件ID的属性,如表1-2所示。
表1-2 相对布局中取值为其他控件ID 的属性及
属性名称 | 属性说明 |
android:layout_toRightOf | 使当前控件位于给出ID |
android:layout_toLeftOf | 使当前控件位于给出ID |
android:layout_above | 使当前控件位于给出ID |
android:layout_below | 使当前控件位于给出ID |
android:layout_alignTop | 使当前控件的上边界位于给出ID |
android:layout_alignBottom | 使当前控件的下边界位于给出ID |
android:layout_alignLeft | 使当前控件的左边界位于给出ID |
android:layout_alignRight | 使当前控件的右边界位于给出ID |
最后要介绍的是属性值以像素为单位的属性及说明,如表1-3所示。
表1-3 相对布局中取值为像素的属性及说明
属性名称 | 属性说明 |
android:layout_marginLeft | 当前控件左侧的留白 |
android:layout_marginRight | 当前控件右侧的留白 |
android:layout_marginTop | 当前控件上方的留白 |
android:layout_marginBottom | 当前控件下方的留白 |
需要注意的是在进行相对布局时要避免出现循环依赖,例如,设置相对布局在父容器中的排列方式为WRAP_CONTENT,就不能再将相对布局的子控件设置为ALIGN_PARENT_BOTTOM。因为这样会造成子控件和父控件相互依赖和参照的错误。
<span style="font-family:Times New Roman;font-size:18px;">public class RelativeLayoutTest extends Activity
{
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
findViewById(R.id.view01).setPadding(5, 5 , 5 , 5);
findViewById(R.id.view02).setPadding(5, 5 , 5 , 5);
findViewById(R.id.view03).setPadding(5, 5 , 5 , 5);
findViewById(R.id.view04).setPadding(5, 5 , 5 , 5);
findViewById(R.id.view05).setPadding(5, 5 , 5 , 5);
}
}</span>
<span style="font-family:Times New Roman;font-size:18px;"><?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<!-- 定义该组件位于父容器中间 -->
<TextView
android:id="@+id/view01"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/leaf"
android:layout_centerInParent="true"
/>
<!-- 定义该组件位于view01组件的上方 -->
<TextView
android:id="@+id/view02"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/leaf"
android:layout_above="@id/view01"
android:layout_alignLeft="@id/view01"
/>
<!-- 定义该组件位于view01组件的下方 -->
<TextView
android:id="@+id/view03"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/leaf"
android:layout_below="@id/view01"
android:layout_alignLeft="@id/view01"
/>
<!-- 定义该组件位于view01组件的左边 -->
<TextView
android:id="@+id/view04"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/leaf"
android:layout_toLeftOf="@id/view01"
android:layout_alignTop="@id/view01"
/>
<!-- 定义该组件位于view01组件的右边 -->
<TextView
android:id="@+id/view05"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/leaf"
android:layout_toRightOf="@id/view01"
android:layout_alignTop="@id/view01"
/>
</RelativeLayout>
</span>
<span style="font-family:Times New Roman;font-size:18px;"><?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="hello">Hello World, RelativeLayoutTest!</string>
<string name="app_name">相对布局</string>
</resources>
</span>
五、网格布局
android4.0以上版本出现的GridLayout布局解决了以上问题。GridLayout布局使用虚细线将布局划分为行、列和单元格,也支持一个控件在行、列上都有交错排列。而GridLayout使用的其实是跟LinearLayout类似的API,只不过是修改了一下相关的标签而已,所以对于开发者来说,掌握GridLayout还是很容易的事情。GridLayout的布局策略简单分为以下三个部分:
首先它与LinearLayout布局一样,也分为水平和垂直两种方式,默认是水平布局,一个控件挨着一个控件从左到右依次排列,但是通过指定android:columnCount设置列数的属性后,控件会自动换行进行排列。另一方面,对于GridLayout布局中的子控件,默认按照wrap_content的方式设置其显示,这只需要在GridLayout布局中显式声明即可。
其次,若要指定某控件显示在固定的行或列,只需设置该子控件的android:layout_row和android:layout_column属性即可,但是需要注意:android:layout_row=”0”表示从第一行开始,android:layout_column=”0”表示从第一列开始,这与编程语言中一维数组的赋值情况类似。
最后,如果需要设置某控件跨越多行或多列,只需将该子控件的android:layout_rowSpan或者layout_columnSpan属性设置为数值,再设置其layout_gravity属性为fill即可,前一个设置表明该控件跨越的行数或列数,后一个设置表明该控件填满所跨越的整行或整列。
六、绝对布局
绝对布局(AbsoluteLayout)能通过指定界面元素的坐标位置,来确定用户界面的整体布局。所谓绝对布局,是指屏幕中所有控件的摆放由开发人员通过设置控件的坐标来指定,控件容器不再负责管理其子控件的位置。由于子控件的位置和布局都通过坐标来指定,因此AbsoluteLayout 类中并没有开发特有的属性和方法。
绝对布局是一种不推荐使用的界面布局,因为通过X轴和Y轴确定界面元素位置后,Android系统不能够根据不同屏幕对界面元素的位置进行调整,降低了界面布局对不同类型和尺寸屏幕的适应能力。每一个界面控件都必须指定坐标(X,Y),例如图5-12中,“确认”按钮的坐标是(40,120),“取消”按钮的坐标是(120,120)。坐标原点(0,0)在屏幕的左上角
<span style="font-family:Times New Roman;font-size:18px;">public class AbsoluteLayoutTest extends Activity
{
//当第一次创建该Activity时回调该方法
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}</span>
<span style="font-family:Times New Roman;font-size:18px;"><?xml version="1.0" encoding="utf-8"?>
<AbsoluteLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<!-- 定义一个文本框,使用绝对定位 -->
<TextView
android:layout_x="20dip"
android:layout_y="20dip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="用户名:"
/>
<!-- 定义一个文本编辑框,使用绝对定位 -->
<EditText
android:layout_x="80dip"
android:layout_y="15dip"
android:layout_width="wrap_content"
android:width="200px"
android:layout_height="wrap_content"
/>
<!-- 定义一个文本框,使用绝对定位 -->
<TextView
android:layout_x="20dip"
android:layout_y="80dip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="密 码:"
/>
<!-- 定义一个文本编辑框,使用绝对定位 -->
<EditText
android:layout_x="80dip"
android:layout_y="75dip"
android:layout_width="wrap_content"
android:width="200px"
android:layout_height="wrap_content"
android:password="true"
/>
<!-- 定义一个按钮,使用绝对定位 -->
<Button
android:layout_x="130dip"
android:layout_y="135dip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="登 录"
/>
</AbsoluteLayout>
</span>
<span style="font-family:Times New Roman;font-size:18px;"><?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="hello">Hello World, AbsoluteLayoutTest!</string>
<string name="app_name">绝对布局</string>
</resources>
</span>