Android中常见的几种布局方式:线性布局(LinearLayout)、相对布局(RelativeLayout)、表格布局(Tablelayout)、嵌套布局(FrameLayout)以及帧布局。
下面通过几个事例来解释一下这几种布局方式:
线性布局,显而易见,从字面上可以看出这周布局方式是在一条线上一样,可以是垂直的(vertical),也可以是水平的(horizontal),下面是一段事例的代码:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
<!--垂直布局-->
android:orientation="vertical" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
<!--给name_text赋值-->
android:text="@string/name_text"
/>
<EditText
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/ok_text"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/cancel_text"
/>
</LinearLayout>
“Layout_width”是指该元素的宽度,可选值有三种:“fill_parent”、“wrap_content”、具体数字(单位为px)。其中“fill_parent”代表填满其父元素,对于顶级元素来说,其父元素就是整个手机屏幕(即在根节点出fill_parent代表的是全屏幕)。“wrap_content”代表该元素的大小仅包裹其自身内容,而数字则代表其占相应的px。
下面是虚拟机上运行的截图:
一般单纯的线性布局做出来的效果比较差,会用嵌套布局,后边嵌套布局会详解。
相对布局,就是利用相对位置布局,添加各个元素后,如果不加布局属性,会全部重叠在一起,下面的例子是一个梅花的形状,效果图是这样的,
它的原理就是,先把上边两个button的属性定义成“置顶”,左边的button用居左,右边的居右,中间的定义为在上边一层的下边和居中,下面的代码中会有详细注释,下边的两个button定义为在上一层的下边和分别居两边。
<?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" >
<Button
<!--给元素一个id-->
android:id="@+id/one"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
<!--居右-->
android:layout_alignParentRight="true"
<!--置顶-->
android:layout_alignParentTop="true"
android:text="@string/btn" />
<Button
<!--给元素一个id-->
android:id="@+id/two"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
<!--居左-->
android:layout_alignParentLeft="true"
<!--置顶-->
android:layout_alignParentTop="true"
android:text="@string/btn" />
<Button
<!--给元素一个id-->
android:id="@+id/three"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
<!--以id为two的元素为基,下移一层-->
android:layout_below="@id/two"
<!--居中-->
android:layout_centerHorizontal="true"
android:text="@string/btn" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
<!--居右-->
android:layout_alignParentRight="true"
<!--以id为three的元素为基,下移一层-->
android:layout_below="@id/three"
android:text="@string/btn" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
<!--居左-->
android:layout_alignParentLeft="true"
<!--以id为three的元素为基,下移一层-->
android:layout_below="@id/three"
android:text="@string/btn" />
</RelativeLayout>
下面说一下表格布局,这个比较容易理解,里边的行是:<TableRow ></TableRow >可以在中间添加元素,下面一个示例:
<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
<!--等比例分-->
android:stretchColumns="*"
>
<TableRow >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/name"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/sex"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/tel"
/>
</TableRow>
<TableRow >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/namels"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/sexls"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/tells"
/>
</TableRow>
<TableRow >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/nameww"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/sexww"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/telww"
/>
</TableRow>
</TableLayout>
效果图:
下面说一下嵌套布局,看下图,这是Android布局的图示,由图可以看出,可以多种布局方式互相包含,这就大大的增加了布局的灵活性。
下边是一个线性布局嵌套线性布局的示例,这是为了更好的实现效果:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
<!--垂直布局-->
android:orientation="vertical" >
<EditText
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<!--注意,从这里开始嵌套,一直到这个标签的结束-->
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="fill_parent"
<!--水平布局-->
android:orientation="horizontal"
android:layout_gravity="center"
>
<Button
android:text="@string/enter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<Button
android:text="@string/reset"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</LinearLayout>
</LinearLayout>
效果图:
下面是一个线性布局嵌套相对布局的示例:
<?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="wrap_content"
android:layout_height="wrap_content"
android:text="@string/name_text"
/>
<EditText
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<!--开始嵌套-->
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/cancel_text"
android:id="@+id/cancel_button"
android:layout_alignParentRight="true"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/ok_text"
android:layout_toLeftOf="@id/cancel_button"
/>
</RelativeLayout>
</LinearLayout>
效果图:
帧布局中的每一个组件都代表一个画面,默认以屏幕左上角作为(0,0)坐标,按组件
定义的先后顺序依次逐屏显示,后面出现的会覆盖前面的画面。用该布局可以实现动画效果。
下面是一个示例,实现一个文字颜色变化过程,实质上是几个图片之间的循环切换:
编写main.xml文件其内容如下:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:id="@+id/frame">
</FrameLayout>
在该布局文件中定义一个id为frame的帧布局文件。在FramerLayoutTestActivity.java中编写java代码:
package cn.class3g.activity;
import android.app.Activity;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.FrameLayout;
public class FrameLayoutTestActivity extends Activity {
FrameLayout frame = null;
private boolean flag = true;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setContentView(R.layout.main);
findViews();
//创建一个Handler子类对象,要调用其他方法
final MyHandler myHandler = new MyHandler();
myHandler.sleep(10);
//为fram设置点击事件,当其被点击时,在开始与暂停直接切换
frame.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
flag = !flag;
myHandler.sleep(10);
}
});
}
private void findViews() {
frame = (FrameLayout) this.findViewById(R.id.frame);
}
//由该类两个方法间的循环调用,实现界面不断更新。
class MyHandler extends Handler {
int i = 0;
public void handleMessage(Message msg) {
i++;
show(i % 6);// 设置frame前景图片
//调用sleep方法
sleep(600);
}
public void sleep(long delayMillis) {
//判断是否继续变换颜色
if (flag) {
//实质上是调用了一次handleMessage
this.sendMessageDelayed(this.obtainMessage(10), delayMillis);
}
}
}
//该方法是被调用以更新帧布局的前景图片
void show(int id) {
//获取6张图片
Drawable[] pic = new Drawable[8];
pic[0] = this.getResources().getDrawable(R.drawable.p1);
pic[1] = this.getResources().getDrawable(R.drawable.p2);
pic[2] = this.getResources().getDrawable(R.drawable.p3);
pic[3] = this.getResources().getDrawable(R.drawable.p4);
pic[4] = this.getResources().getDrawable(R.drawable.p5);
pic[5] = this.getResources().getDrawable(R.drawable.p6);
frame.setForeground(pic[id]);
}
}
效果图:
由于FrameLayout中后出现的UI控件会覆盖前面出现的UI控件,每次只能显示一个UI控
件,因此,我们可以通过在Activity中对每次显示的图片内容进行切换以实现动画效果。或许可以开启一条线程来控制切换,但在非主线程中不能更新UI界面,所以,使用了Android提供的消息通讯类Handler。该类可以实现非主线程和负责UI的主线程之间的通信,进而间接实现非主线程更新UI界面。由于sleep方法中的sendMessageDelayed(obtainMessage(0),delayMillis);本身会延迟发送一个消息,该消息会被框架传递给handleMessage事件。我们在handleMessage()方法中再次调用sleep()方法,
形成一个循环调用。在我们对界面进行点击之前,两个方法会一直循环调用。前景图片也会不断的切换,进而实现动画的效果。
2011年12月7日21:11:06