zoukankan      html  css  js  c++  java
  • 【Android】Android六种布局详解

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

    1.LinearLayout布局

    线性布局,两种排法:

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

    LinearLayout
    一个竖向的大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 离某元素下边缘的距离

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

    RelativeLayout
    注意

    • 如果没有定义左右,那么默认在左边,如果没有定义上下,默认在上边。
    • 相同位置,新定义的元素会覆盖旧的元素。例: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>

    最后效果如图:
    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>

    实际效果如下:
    FrameLayout

    5.TableLayout布局

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

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

    还有几个重要属性:

    • 写在TableLayout中的属性
      • android:stretchColumns 设置第几列为伸展(0表示第一列)
      • android:shrinkColumns 设置第几列为收缩
      • android:collapseColumns 设置第几列为隐藏
    • 写在TableRow里的控件里的属性
      • android:layout_column 设置控件在第几列
      • android:layout_span 设置控件能跨多少列
      • android:gravity 设置控件的排列方式,可以水平居中,水平靠左,水平靠右,垂直居中,垂直靠右,垂直靠左

    代码如下:

    <?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>

    最后效果如下:
    TableLayout

    如果想要设置两个一个并排显示的,可以参考下面的代码:

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/daylimit_content_alter"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
    
        <TableLayout
            android:layout_width="fill_parent"
            android:layout_height="50dp"
            android:layout_alignParentBottom="true"
            android:collapseColumns="2" >
    
            <TableRow android:gravity="center_horizontal" >
    
                <Button
                    android:layout_weight="0.5"
                    android:onClick="CopyBtn"
                    android:text="复制" />
    
                <Button
                    android:layout_weight="0.5"
                    android:onClick=""
                    android:text="返回" />
            </TableRow>
        </TableLayout>
    
    </RelativeLayout>

    效果图:

    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>

    最后效果如下:
    AbsoluteLayout

    原文连接:http://blog.csdn.net/u013254061/article/details/52512146

  • 相关阅读:
    Git: git tag 使用小结(给发布版本打标记,切换并修改某个历史版本)
    android: Android水波纹点击效果
    Flutter: 运行新项目报错
    FFmpeg编译:mac下编译iOS平台的FFmpeg库(支持armv7, arm64, i386, x86_64)
    Xcode: Xcode中Command Line Tools的安装方法
    win10: windows+E 改回打开我的电脑
    DialogFragment: DialogFragment的一些理解
    Android Studio: 查看SDK源代码
    HandlerThread: HandlerThread的理解
    Looper: Looper,Handler,MessageQueue三者之间的联系
  • 原文地址:https://www.cnblogs.com/HDK2016/p/7688821.html
Copyright © 2011-2022 走看看