这篇就对LinearLayout、RelativeLayout、自定义ViewGroup、FrameLayout、TableLayout、AbsoluteLayout六种布局进行详细的讲解。

1.LinearLayout布局

线性布局,两种排法:

  • 从左到右
    android:orientation=”horizontal”
  • 从上到下
    android:orientation=”vertical”
    具体上图


一个竖向的大LinearLayout嵌套着两个小LinearLayout,第一个小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">    <LinearLayout            android:layout_width="match_parent"            android:layout_height="250dp"            android:orientation="horizontal">            <TextView                   android:layout_width="96dp"              android:layout_height="match_parent"         android:background="#b2dfdb" />            <TextView                    android:layout_width="96dp"                       android:layout_height="match_parent"                     android:background="#80cbc4" />            <TextView                    android:layout_width="96dp"                           android:layout_height="match_parent"                    android:background="#4db6ac" />            <TextView                    android:layout_width="96dp"                    android:layout_height="match_parent"                    android:background="#26a69a" />    LinearLayout>    <LinearLayout            android:layout_width="match_parent"                android:layout_height="match_parent"            android:orientation="vertical">            <TextView                   android:layout_width="match_parent"                    android:layout_height="68dp"                    android:background="#b2dfdb" />            <TextView                    android:layout_width="match_parent"                        android:layout_height="68dp"                    android:background="#80cbc4" />            <TextView                    android:layout_width="match_parent"                        android:layout_height="68dp"                    android:background="#4db6ac" />            <TextView                    android:layout_width="match_parent"                            android:layout_height="68dp"                    android:background="#26a69a" />    LinearLayout>LinearLayout>

2.RelativeLayout布局

参考其他控件进行布局,默认为父控件。
有三种类型的属性:

  • 属性值是true或false
    • android:layout_centerHrizontal 水平居中
    • android:layout_centerVertical 垂直居中
    • android:layout_centerInparent 相对于父元素完全居中。
    • android:layout_alignParentBottom 位于父元素的下边缘
    • android:layout_alignParentTop 位于父元素的上边缘
    • android:layout_alignParentLeft 位于父元素的左边缘
    • android:layout_alignParentRight 位于父元素的右边缘
  • 属性值是”@id/*“
    • android:layout_below 在某元素的下方
    • android:layout_above 在某元素的上方
    • andorid:layout_toRightOf 在某元素的右方
    • android:layout_toLeftOf 在某元素的左方
    • android:layout_alignBottom 和某元素下方对齐
    • android:layout_alignTop 和某元素上方对齐
    • android:layout_alignRight 和某元素右方对齐
    • android:layout_alignLeft 和某元素左方对齐
  • 属性值是数值
    • android:layout_marginLeft 离某元素左边缘的距离
    • android:layout_marginRight 离某元素右边缘的距离
    • android:layout_marginTop 离某元素上边缘的距离
    • android:layout_marginBottom 离某元素下边缘的距离

各取一个来写例子,如图。


注意

  • 如果没有定义左右,那么默认在左边,如果没有定义上下,默认在上边。
  • 相同位置,新定义的元素会覆盖旧的元素。例:1被2覆盖了。
  • 4只定义了在父元素的下部,左右没有定义,于是默认就在左边了。
  • android:layout_below,在某元素的下部并不意味着就一定是紧随某元素,只是在下部的默认位置。例如:5是在3的下部,但是是在下部的默认左边。
  • 6为下边缘对齐3,7为marginLeft=150dp。
  • 8为多个属性共同定义的结果。首先是在3的右部,然后是垂直居中,然后marginLeft=100dp得到最后位置。

代码如下:

<?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"    android:orientation="vertical">    <TextView        style="@style/btn_relative"        android:text="1" />    <TextView        style="@style/btn_relative"        android:text="2" />    <TextView        android:id="@+id/txt_center"        style="@style/btn_relative"        android:layout_centerInParent="true"        android:text="3" />    <TextView        style="@style/btn_relative"        android:layout_alignParentBottom="true"        android:text="4" />    <TextView        style="@style/btn_relative"        android:layout_below="@id/txt_center"        android:background="#d0d9ff"        android:text="5" />    <TextView        style="@style/btn_relative"        android:layout_alignBottom="@+id/txt_center"        android:text="6" />    <TextView        style="@style/btn_relative"        android:layout_marginLeft="150dp"        android:text="7" />    <TextView        style="@style/btn_relative"        android:layout_centerVertical="true"        android:layout_marginLeft="100dp"        android:layout_toRightOf="@id/txt_center"        android:text="8" />RelativeLayout>

3.MyLayout布局(自定义ViewGroup)

自定义布局主要是重写两个方法:

  • onMeasure() 这个是写自定义容器的大小。
  • onLayout() 这个是写子元素的布局。
    我自己写了一个自定义布局,是顺序填充会延对角线进行排列。

3.1onMeasure()

 @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        /**         * 获得此ViewGroup上级容器为其推荐的宽和高,以及计算模式         */        int widthMode = MeasureSpec.getMode(widthMeasureSpec);        int heightMode = MeasureSpec.getMode(heightMeasureSpec);        int sizeWidth = MeasureSpec.getSize(widthMeasureSpec);        int sizeHeight = MeasureSpec.getSize(heightMeasureSpec);        // 计算出所有的childView的宽和高        measureChildren(widthMeasureSpec, heightMeasureSpec);        /**         * width和height是当wrap_content时使用的属性。         */        int width = 0;        int height = 0;        int cCount = getChildCount();        int cWidth = 0;        int cHeight = 0;        /**         * 在这里计算当wrap_content时,布局的大小。         */        for (int i = 0; i < cCount; i++) {            View childView = getChildAt(i);            cWidth = childView.getMeasuredWidth();            cHeight = childView.getMeasuredHeight();            width += cWidth;            height += cHeight;        }        /**         * 如果是wrap_content设置为我们计算的值         * 否则:直接设置为父容器计算的值         */        setMeasuredDimension((widthMode == MeasureSpec.EXACTLY) ? sizeWidth                : width, (heightMode == MeasureSpec.EXACTLY) ? sizeHeight                : height);    }

首先要说一下布局计算模式,即最后的EXACTLY。一共有三种计算模式:

  • MeasureSpec.EXACTLY:精确尺寸,相当于具体数值和match_parent。
  • MeasureSpec.AT_MOST:最大尺寸,相当于 warp_content。
  • MeasureSpec.UNSPECIFIED:未指定尺寸,这种情况不多,一般用于AdapterView。

最后的设定大小时,如果是精确尺寸就是用sizeWidth即获取的尺寸,如果是最大尺寸就是要我们自己计算的那个尺寸了。
onMeasure()最主要的功能就是计算wrap_content的尺寸设置尺寸
我将这个方法称为“建画布”,先建了画布才能在上面绘图嘛。

3.2 onLayout()

@Override    protected void onLayout(boolean changed, int l, int t, int r, int b) {        int cCount = getChildCount();        /**         * 遍历所有childView根据其宽和高,以及margin进行布局         */        for (int i = 0; i < cCount; i++) {            View childView = getChildAt(i);            r = l + childView.getMeasuredWidth();            b = t + childView.getMeasuredHeight();            childView.layout(l, t, r, b);            l += childView.getMeasuredWidth();            t += childView.getMeasuredHeight();        }    }

这个方法的作用是设置摆放子元素的位置。其中onLayout()传入的l、t、r、b分别是这样

  • l,t分别对应子元素左上角的left,top坐标
  • r,b分别对应子元素右下角的right,bottom坐标

并且可以使用childview.getMeasuredWidth()和childView.getMeasureHeight()得到子元素的宽和高。
这样就可以来对每个子元素进行布局了。
我称这个方法为“定位置”。定完位置后那么子元素就被放到了我们想要的地方。
这样一个自定义ViewGroup就可以使用了。
xml文件如下:

<?xml version="1.0" encoding="utf-8"?><com.example.layoutdemo.MyLayout.MyLayout    xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="wrap_content"    android:layout_height="wrap_content"    >        <TextView            android:layout_width="50dp"            android:layout_height="50dp"            android:background="#b2dfdb" />        <TextView            android:layout_width="50dp"            android:layout_height="50dp"            android:background="#80cbc4" />        <TextView            android:layout_width="50dp"            android:layout_height="50dp"            android:background="#4db6ac" />        <TextView            android:layout_width="50dp"            android:layout_height="50dp"            android:background="#26a69a" />com.example.layoutdemo.MyLayout.MyLayout>

最后效果如图:

4.FrameLayout布局

帧布局,这个布局的特点是从左上角开始,后面的会覆盖前面的控件。
代码如下:

<?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"    android:orientation="vertical">    <TextView        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:textSize="100dp"        android:textColor="#9c27b0"        android:text="第一层"/>    <TextView        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:textSize="80dp"        android:textColor="#e91e63"        android:text="第二层"/>    <TextView        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:textSize="60dp"        android:textColor="#e51c23"        android:text="第三层"/>    <TextView        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:textSize="40dp"        android:textColor="#5677fc"        android:text="第四层"/>FrameLayout>

实际效果如下:

5.TableLayout布局

表格布局。
它遵循着以下结构:

<TableLayout>    <TableRow>    <!-在这里填充第一行的元素->    TableRow>    <TableRow>    <!-在这里填充第二行的元素->    TableRow>    TableLayout>

还有几个重要属性:

  • 写在TableLayout中的属性
    • android:stretchColumns 设置第几列为伸展(0表示第一列)
    • android:shrinkColumns 设置第几列为收缩
    • android:collapseColumns 设置第几列为隐藏
  • 写在TableRow里的控件里的属性
    • android:layout_column 设置控件在第几列
    • android:layout_span 设置控件能跨多少列

代码如下:

<?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:collapseColumns="2"    android:shrinkColumns="1"    android:stretchColumns="0">    <TableRow       >        <TextView android:text="我是伸展的第一列" />        <TextView android:text="我是收缩的第二列" />        <TextView android:text="我被隐藏了" />    TableRow>    <TableRow>        <TextView android:text="我可以伸展的很长很长很长长" />        <TextView android:text="我可以收缩,我可以变的很深很深很深" />        <TextView android:text="我被隐藏了T_T" />    TableRow>    <TableRow>        <TextView            android:layout_column="1"            android:text="我要在第2列" />    TableRow>    <TableRow>        <TextView            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_column="0"            android:layout_span="2"            android:text="我要               跨                  两                列" />    TableRow>TableLayout>

最后效果如下:

6.AbsoluteLayout布局

绝对布局,极力不推荐,官方已经舍弃。
定义两个控件左上角坐标轴
android:layout_xandroid:layout_y来控制位置。

<?xml version="1.0" encoding="utf-8"?><AbsoluteLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent">    <TextView        style="@style/btn_relative"        android:text="1" />    <TextView        style="@style/btn_relative"        android:layout_x="60dp"        android:layout_y="60dp"        android:text="1" />    <TextView        style="@style/btn_relative"        android:layout_x="160dp"        android:layout_y="160dp"        android:text="1" />    <TextView        style="@style/btn_relative"        android:layout_x="260dp"        android:layout_y="260dp"        android:text="1" />AbsoluteLayout>

最后效果如下:

源码下载地址:LayoutDemo

更多相关文章

  1. Android(安卓)ConstraintLayout 约束布局
  2. ImageView的scaletype属性
  3. Android查看系统信息
  4. 自定义ProgressBar的样式失效
  5. Android中visibility属性VISIBLE、INVISIBLE、GONE的区别
  6. ANDROID 【GRIDVIEW】 DETAILED ANNOTATION
  7. Android之Audio常用属性变量
  8. android 之 Attr的使用
  9. Android(安卓)TextView中android:textIsSelectable属性在Recycle

随机推荐

  1. Android-TextView
  2. Android(安卓)WebView全面讲解
  3. Android5.0之后 VectorDrawable实现超炫
  4. Android(安卓)多进程通信
  5. Android如何解析Intent Filter
  6. 谈谈android数据存储方式
  7. Android(安卓)动画实现
  8. 解决windows下eclipse中android项目关联a
  9. android 视频播放器 android videoView
  10. Uncaught Error: Error calling method o