精华内容
下载资源
问答
  • android 布局

    千次阅读 2010-04-25 15:00:00
    android学习笔记(一 android布局学习)转自http://blog.sina.com.cn/s/blog_61c62a960100ev3q.html(2009-09-20 20:50:44)(){

    android学习笔记(一 android布局学习)

    转自http://blog.sina.com.cn/s/blog_61c62a960100ev3q.html

    (2009-09-20 20:50:44)
    标签:

    it

    分类:android

      最近痴迷上了android , 因为有java 语言的基础学起来自己感觉很快。但是毕竟是做java ee的,这一下转到手机上还是有那么点不适应。为了把自己的学习成果总结一下,特写了这个android系列的学习笔记,下面进入正题

      我的android开发环境是搭建在windows xp系统下的,搭建过程很简单。使用了MyEclipse6.5,sdk1.5_r2,jdk_1.6,以及ADT。最后输出了一个hello word。 有了这一步,我便进入了下一步的学习。我认为学android还是应该先学他的 布局方式以及控件的用途。这也是今天我想写在我的学习笔记里的内容。

     第一次仔细看android的一个程序,发现他有很多的xml文件。当时想的第一个问题就是,这些xml文件之间是如何进行关联的?假如我要自己写一个android程序,我应该先写什么?或者先配置什么?还是写完以后可以实现自动配置?带着这些问题 我进入了android布局的学习。

      android我目前所学习到的布局方式有以下几种:

    1. LineraLayout局部 线性布局

    感觉这个布局方式是最常见的一种。它有两种布局方式:行 与列。是由参数orientation(方位)决定的。vertical表示竖直排列,horizontal表示横向排列.

    具体代码如

      <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:orientation="vertical" android:layout_width="fill_parent"
     android:layout_height="fill_parent">

     每个参数都要以android:开头。一般都有android:layout_width和android:layout_height 具体的值有两个一个是fill_parent 一个是wrap_content  每一个布局都是一个容器,layout_width与height表示这个容器的宽 与高是填充满父容器,还是依赖于他本身的内容

    2. FrameLayout布局 框架布局

    这个布局一般是放图片的,放入其中的所有元素都被放置在FrameLayout区域最左上的区域,而且无法为这些元素指定一个确切的位置。如果一个FrameLayout里有多个子元素,那么后边的子元素的显示会重叠在前一个元素上。这个布局方式的宽与高的参数一般是用wrap_content。

    3. RelativeLayout布局 相对布局

    这个布局很常见。具体代码比如:

    <RelativeLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="fill_parent" android:layout_height="wrap_content"
     android:background="@drawable/blue" android:padding="10dip">

     <TextView android:id="@+id/label" android:layout_width="fill_parent"
      android:layout_height="wrap_content" android:text="请输入用户名:" />

     <!--
      这个EditText放置在上边id为label的TextView的下边
     -->
     <EditText android:id="@+id/entry" android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:background="@android:drawable/editbox_background"
      android:layout_below="@id/label" />

     <!--
      取消按钮和容器的右边齐平,并且设置左边的边距为10dip
     -->
     <Button android:id="@+id/cancel" android:layout_width="wrap_content"
      android:layout_height="wrap_content" android:layout_below="@id/entry"
      android:layout_alignParentRight="true"
      android:layout_marginLeft="10dip" android:text="取消" />

     <!--
      确定按钮在取消按钮的左侧,并且和取消按钮的高度齐平
     -->
     <Button android:id="@+id/ok" android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_toLeftOf="@id/cancel"
      android:layout_alignTop="@id/cancel" android:text="确定" />

    </RelativeLayout>
    在这个容器里放置了一些组件,每个组件里多了一些对他们位置关系的描述,比如android:layout_below="@id/label" 表示放在id为label的控件下面== 要注意的是,如果组件B依赖于A,那么必须要让A出现在B的前面。

    padding表示填充,margin表示边距。android当中最常见的支持描述大小区域的类型如下 px像素 dip依赖于设备的像素.

    4. TableLayout 表格布局

    <TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="fill_parent" android:layout_height="fill_parent"
     android:stretchColumns="1">

     <TableRow>
      <TextView android:text="用户名:" android:textStyle="bold"
       android:gravity="right" android:padding="3dip" />

      <EditText android:id="@+id/username" android:padding="3dip"
       android:scrollHorizontally="true" />
     </TableRow>

     <TableRow>
      <TextView android:text="登录密码:" android:textStyle="bold"
       android:gravity="right" android:padding="3dip" />

      <EditText android:id="@+id/password" android:password="true"
       android:padding="3dip" android:scrollHorizontally="true" />
     </TableRow>

     <TableRow android:gravity="right">

      <Button android:id="@+id/cancel"
       android:text="取消" />

      <Button android:id="@+id/login"
       android:text="登录"  android:layout_width="wrap_content"
       android:layout_height="wrap_content"/>
     </TableRow>
    </TableLayout>

    里面是由多个TableRow组成的。一行一行的很好理解。

    布局方式是可以组合在一起的。这个也不难理解。

    这个布局的学习笔记就先写到这里。

    展开全文
  • xamarin android布局

    千次阅读 2016-09-09 13:23:09
    xamarin android布局练习(1) xamarin android布局练习,基础非常重要,首先要学习的就是android的布局练习,xamarin也一样,做了几个xamarin android的布局例子,多练习几遍就能学会这个布局,当然有写css的学习...

    xamarin android布局练习(1)

    xamarin android布局练习,基础非常重要,首先要学习的就是android的布局练习,xamarin也一样,做了几个xamarin android的布局例子,多练习几遍就能学会这个布局,当然有写css的学习这个android的布局很容易入门。

    当你看到这篇文章的时候,你应该知道字体图标,下面很多图标都是直接从上面下载的,非常的牛逼,这个字体图标有必要科普一下,这个链接

    字体图标下载

    首先来看看要做成什么样子的

    主要的关键点就是:gravity对其方式,relative布局, linear布局,width,height,orientation方向

    代码:

     

    <?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:background="#dedede"
        android:id="@+id/relativeLayout">
        <LinearLayout
            android:id="@+id/linear1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="#c6c6c6"
            android:gravity="center">
            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="请登录"
                android:textSize="20sp"
                android:gravity="center"
                android:layout_marginTop="20dp"
                android:layout_marginBottom="20dp"
                android:textColor="#808080" />
        </LinearLayout>
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@+id/linear1"
            android:orientation="vertical"
            android:id="@+id/linear2">
        <!--相对布局-->
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="horizontal"
                android:clickable="true"
                android:id="@+id/linear3">
                <ImageView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:src="@drawable/xiaoxi"
                    android:layout_gravity="center"
                    android:layout_marginLeft="10dp" />
                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:text="@string/xiaoxi"
                    android:textColor="@color/test_bg"
                    android:gravity="center"
                    android:textSize="30sp"
                    android:layout_marginTop="10dp"
                    android:layout_marginBottom="10dp" />
            </LinearLayout>
            <View
                android:layout_width="match_parent"
                android:layout_height="1dp"
                android:background="#999999" />
        </LinearLayout>
        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_below="@+id/linear2"
            android:id="@+id/linear4"
            android:orientation="vertical"
            android:clickable="true">
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="horizontal">
                <ImageView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:src="@drawable/school"
                    android:layout_gravity="center"
                    android:layout_marginLeft="10dp" />
                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:text="校园活动"
                    android:textSize="30sp"
                    android:textColor="#808080"
                    android:gravity="center"
                    android:layout_marginTop="10dp"
                    android:layout_marginBottom="10dp" />
            </LinearLayout>
            <View
                android:layout_height="1dp"
                android:layout_width="match_parent"
                android:background="#999999" />
        </LinearLayout>
        <LinearLayout
            android:orientation="vertical"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@+id/linear4"
            android:clickable="true">
            <LinearLayout
                android:orientation="horizontal"
                android:layout_width="match_parent"
                android:layout_height="wrap_content">
                <ImageView
                    android:id="@+id/img1"
                    android:src="@drawable/taobao"
                    android:layout_gravity="center"
                    android:layout_height="wrap_content"
                    android:layout_width="wrap_content"
                    android:layout_marginLeft="10dp" />
                <TextView
                    android:text="@string/taobao"
                    android:textColor="@color/test_bg"
                    android:textSize="30sp"
                    android:layout_height="wrap_content"
                    android:layout_width="match_parent"
                    android:layout_marginTop="10dp"
                    android:layout_marginBottom="10dp"
                    android:gravity="center" />
            </LinearLayout>
        </LinearLayout>
    </RelativeLayout>

    xamarin android布局练习(2)

    看看效果图2

    代码如下:

     

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_height="match_parent"
        android:layout_width="match_parent"
        android:id="@+id/linear1"
        android:orientation="vertical">
        <LinearLayout
            android:layout_height="wrap_content"
            android:layout_width="match_parent"
            android:id="@+id/linear2"
            android:orientation="vertical"
            android:background="#dedede">
            <TextView
                android:layout_height="wrap_content"
                android:layout_width="match_parent"
                android:textColor="#808080"
                android:textSize="20dp"
                android:text="如何使用xamarin布局练习"
                android:layout_marginTop="10dp"
                android:layout_marginBottom="10dp" />
            <RelativeLayout
                android:layout_height="wrap_content"
                android:layout_width="match_parent"
                android:id="@+id/relative1">
                <ImageView
                    android:id="@+id/imgCenter"
                    android:layout_height="100dp"
                    android:layout_width="100dp"
                    android:layout_centerInParent="true"
                    android:src="@drawable/taobao" />
                <ImageView
                    android:id="@+id/imgLeft"
                    android:layout_alignParentLeft="true"
                    android:layout_height="100dp"
                    android:layout_width="100dp"
                    android:src="@drawable/taobao1" />
                <ImageView
                    android:id="@+id/imgRight"
                    android:layout_alignParentRight="true"
                    android:layout_height="100dp"
                    android:layout_width="100dp"
                    android:src="@drawable/taobao1" />
            </RelativeLayout>
            <LinearLayout
                android:layout_height="wrap_content"
                android:layout_marginTop="10dp"
                android:layout_width="match_parent"
                android:orientation="horizontal"
                android:id="@+id/relative2">
                <TextView
                    android:textColor="#999999"
                    android:textSize="15dp"
                    android:text="手机腾讯网"
                    android:id="@+id/txt1"
                    android:layout_height="wrap_content"
                    android:layout_width="wrap_content" />
                <TextView
                    android:textColor="#999999"
                    android:textSize="15dp"
                    android:text="评论  89"
                    android:layout_height="wrap_content"
                    android:layout_width="wrap_content"
                    android:layout_gravity="right" />
            </LinearLayout>
            <View
                android:layout_height="1dp"
                android:layout_width="match_parent"
                android:background="#808080" />
        </LinearLayout>
        <LinearLayout
            android:layout_height="wrap_content"
            android:layout_width="match_parent"
            android:id="@+id/linear21"
            android:orientation="vertical"
            android:background="#dedede"
            android:layout_marginTop="10dp">
            <TextView
                android:layout_height="wrap_content"
                android:layout_width="match_parent"
                android:textColor="#808080"
                android:textSize="20dp"
                android:text="如何使用xamarin布局练习2"
                android:layout_marginTop="10dp"
                android:layout_marginBottom="10dp" />
            <RelativeLayout
                android:layout_height="wrap_content"
                android:layout_width="match_parent"
                android:id="@+id/relative11">
                <ImageView
                    android:id="@+id/imgCenter1"
                    android:layout_height="100dp"
                    android:layout_width="100dp"
                    android:layout_centerInParent="true"
                    android:src="@drawable/taobao" />
                <ImageView
                    android:id="@+id/imgLeft1"
                    android:layout_alignParentLeft="true"
                    android:layout_height="100dp"
                    android:layout_width="100dp"
                    android:src="@drawable/taobao1" />
                <ImageView
                    android:id="@+id/imgRight1"
                    android:layout_alignParentRight="true"
                    android:layout_height="100dp"
                    android:layout_width="100dp"
                    android:src="@drawable/taobao1" />
            </RelativeLayout>
            <LinearLayout
                android:layout_height="wrap_content"
                android:layout_marginTop="10dp"
                android:layout_width="match_parent"
                android:orientation="horizontal"
                android:id="@+id/relative21">
                <TextView
                    android:textColor="#999999"
                    android:textSize="15dp"
                    android:text="手机腾讯网"
                    android:id="@+id/txt11"
                    android:layout_height="wrap_content"
                    android:layout_width="wrap_content" />
                <TextView
                    android:textColor="#999999"
                    android:textSize="15dp"
                    android:text="评论  89"
                    android:layout_height="wrap_content"
                    android:layout_width="wrap_content"
                    android:layout_gravity="right" />
            </LinearLayout>
        </LinearLayout>
    </LinearLayout>

    主要的关键点在于:relative布局,

     android:layout_alignParentLeft="true"

    这个属性非常重要,在父容器中的对其方式,bool类型的。layout_alignParentLeft="true"在父容器中左对齐

    xamarin android布局练习(3)

    效果图:

     

     

    代码如下:

     

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_height="match_parent"
        android:layout_width="match_parent"
        android:id="@+id/relative"
        android:background="#dedede">
        <ImageView
            android:layout_height="64dp"
            android:layout_width="64dp"
            android:id="@+id/imgCenter"
            android:src="@drawable/taobao"
            android:layout_centerInParent="true" />
        <ImageView
            android:layout_height="64dp"
            android:layout_width="64dp"
            android:id="@+id/imgTop"
            android:src="@drawable/wangwang"
            android:layout_above="@+id/imgCenter"
            android:layout_centerHorizontal="true" />
        <ImageView
            android:layout_height="64dp"
            android:layout_width="64dp"
            android:id="@+id/imgRight"
            android:src="@drawable/suning"
            android:layout_toRightOf="@+id/imgCenter"
            android:layout_centerVertical="true" />
        <ImageView
            android:layout_height="64dp"
            android:layout_width="64dp"
            android:id="@+id/imgLeft"
            android:src="@drawable/suning"
            android:layout_toLeftOf="@+id/imgCenter"
            android:layout_centerVertical="true" />
        <ImageView
            android:layout_height="64dp"
            android:layout_width="64dp"
            android:id="@+id/imgBottom"
            android:src="@drawable/jingsong"
            android:layout_below="@+id/imgCenter"
            android:layout_centerHorizontal="true" />
    </RelativeLayout>


    关键点在于如何使用relative的各种对其方式

     

     

     

     

     

     

    xamarin android布局练习简单的登录(4)

    效果如下:

    只用了一个linear布局

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/loginBgColor">
        <LinearLayout
            android:layout_height="wrap_content"
            android:layout_width="match_parent"
            android:id="@+id/linear1"
            android:orientation="vertical">
            <TextView
                android:id="@+id/txt"
                android:layout_height="wrap_content"
                android:layout_width="wrap_content"
                android:layout_marginTop="30dp"
                android:layout_marginBottom="30dp"
                android:layout_marginRight="30dp"
                android:layout_gravity="right"
                android:text="设备登录"
                android:textColor="@color/whiteColor"
                android:textSize="20dp" />
        </LinearLayout>
        <LinearLayout
            android:id="@+id/linear2"
            android:layout_height="wrap_content"
            android:layout_width="match_parent"
            android:orientation="vertical">
            <TextView
                android:id="@+id/txt2"
                android:layout_height="wrap_content"
                android:layout_width="wrap_content"
                android:textSize="30dp"
                android:textColor="@color/whiteColor"
                android:layout_gravity="center"
                android:text="LOGO"
                android:layout_marginTop="20dp"
                android:layout_marginBottom="20dp" />
        </LinearLayout>
        <LinearLayout
            android:id="@+id/linear3"
            android:layout_height="wrap_content"
            android:layout_width="match_parent"
            android:orientation="vertical"
            android:layout_marginLeft="20dp"
            android:layout_marginRight="20dp">
            <EditText
                android:id="@+id/txtUserName"
                android:background="@color/whiteColor"
                android:hint="请输入用户名"
                android:focusable="true"
                android:layout_width="match_parent"
                android:layout_height="50dp"
                android:textSize="20dp"
                android:textColor="#000000"
                android:paddingLeft="10dp"
                android:textCursorDrawable="@null" />
            <View
                android:layout_width="match_parent"
                android:layout_height="1dp"
                android:background="#dedede" />
            <EditText
                android:id="@+id/txtPassword"
              android:background="@color/whiteColor"
                android:hint="请输入密码1"
                android:textCursorDrawable="@null"
                android:inputType="textPassword"
                android:layout_width="match_parent"
                android:layout_height="50dp"
                android:textSize="20dp"
                android:paddingLeft="10dp"
                android:textColor="#000000" />
            <Button
                android:id="@+id/btnLogin"
                android:text="登录"
                android:layout_height="50dp"
                android:layout_width="match_parent"
                android:textColor="@color/whiteColor"
                android:background="#2894FF"
                android:textSize="20dp"
                android:paddingTop="5dp"
                android:paddingBottom="5dp"
                android:layout_marginTop="20dp" />
        </LinearLayout>
        <LinearLayout
            android:layout_height="wrap_content"
            android:layout_width="match_parent"
            android:orientation="horizontal"
            android:layout_marginLeft="20dp"
            android:layout_marginTop="10dp"
            android:id="@+id/linear5">
            <CheckBox
                android:id="@+id/checkbox_remeberUser"
                android:layout_height="30dp"
                android:layout_width="30dp"
                android:textColor="#336699"
                android:textColorHighlight="#336699" />
            <TextView
                android:id="@+id/remeberUser"
                android:layout_height="wrap_content"
                android:layout_width="wrap_content"
                android:text="记住该用户"
                android:textColor="#FFFFFF"
                android:textSize="16dp" />
        </LinearLayout>
    </LinearLayout>

    关注我的微信公众号:dotNet全栈开发 ,一个专注.net全栈的公众号

     

    展开全文
  • android编程 第三讲 Android布局管理器 文章目录android编程 第三讲 Android布局管理器约束布局管理器ConstraintLayout线性布局管理器LinearLayout表格布局管理器TableLayout帧布局管理器FrameLayout相对布局管理器...

    android编程 第三讲 Android布局管理器

    约束布局管理器ConstraintLayout

    基于条件的布局允许你根据图层和它同级图层或者它的父图层的相应关系指定图层的位置和大小。通过CAConstraint类描述的关系被保存在子图层的constraints数组属性里面。

    当使用约束布局的时候,你首先创建一个CAConstraintLayoutManager的实例,并把它设置为父图层的布局管理器。然后你通过实例化CAConstraint对象为子图层创建约束条件,并把这些约束条件通过使用addConstraint:方法添加到子图层的约束属性里面。每个CAConstraint实例封装了一个两个图层在同一轴上的几何关系。

    同级层引用的名称,使用图层的name属性。特定的名称superlayer被使用来引用图层的父图层。

    每个轴上面最多只能指定两个关系。如果你给图层的左边和右边都指定约束关系,那么图层的宽度就会不同。如果你给图层的左边和宽度指定约束关系,则图层的右边就会从根据父图层的frame移动。通常你一般只会指定单个边的约束条件,图层在同一个轴上面的大小将会作为第二个约束关系。

    线性布局管理器LinearLayout

    一、线性布局LinearLayout最常用的属性有:

    1.android:orientation
    设置布局管理器内组件的排列方式,可以设置为 horizontal (水平排列)、vertical (垂直排列)。

    2.android:layout_width
    设置布局管理器的宽度,可以设置为wrap_content(包裹大小)、match_parent(填充父控件)、指定大小(单位dp)。

    3.android:layout_height
    设置布局管理器的高度,可以设置为wrap_content(包裹大小)、match_parent(填充父控件)、指定大小(单位dp)。

    4.android:gravity
    设置布局管理器内组件的对齐方式,该属性值可设为 top(顶部对齐) 、bottom(底部对齐) 、left(左对齐) 、right(右对齐) 、center_vertical(垂直方向居中) 、 fill_vertical(垂直方向填充) 、 center_horizontal(水平方向居中) 、 fill_horizontal(水平方向填充) 、center(垂直与水平方向都居中) 、 fill (填充)、 clip_vertical(垂直方向裁剪) 、 clip_horizontal(水平方向裁剪) 。
    注意:可同时指定多种对其方式的组合,中间用“|”连接,如下方代码设置对齐方式为 left|center_vertical 表示出现在屏幕左边且垂直居中

    5.android:layout_gravity
    设置view在其父view中的对其方式。 该属性值可设为 top(顶部对齐) 、bottom(底部对齐) 、left(左对齐) 、right(右对齐) 、center_vertical(垂直方向居中) 、 fill_vertical(垂直方向填充) 、 center_horizontal(水平方向居中) 、 fill_horizontal(水平方向填充) 、center(垂直与水平方向都居中) 、 fill (填充)、 clip_vertical(垂直方向裁剪) 、 clip_horizontal(水平方向裁剪) 。

    6.android:padding
    设置元素与边框之间的距离(外间距),这是一次设置四个方向。单独设置某个方向有另外四个属性分别是android:paddingTop(元素的上面)、android:paddingBottom(元素的下面)、android:paddingLeft(元素的左边)、android:paddingRight(元素的右边)。

    7.android:layout_margin
    设置相对于父控件之间的距离(内间距),这是一次设置四个方向。单独设置某个方向有另外四个属性分别是android:layout_marginTop、android:layout_marginBottom、android:layout_marginLeft、android:layout_marginRight。

    8.android:layout_weight
    设置控件在父布局的比重,通过百分百比来进行布局。需要注意的是,使用weight需要将android:layout_width或者android:layout_height属性设置为0或0px,不这样设置可以与你想要的效果不一样。

    9.android:background
    设置控件的背景,可以是图片或者颜色。

    表格布局管理器TableLayout

    TableLayout布局中并不会为每一行、每一列或每个单元格绘制边框,每一行可以有0个或多个单元格,每个单元格为一个View对象。TableLayout中可以有空的单元格,单元格也可以像HTML中那样跨越多个列。

    在TableLayout布局中,一个列的宽度由该列中最宽的那个单元格指定,而表格的宽度是由父容器指定的。在TableLayout中,可以为列设置三种属性:

    • Shrinkable:如果一个列被标识为Shrinkable,则该列的宽度可以进行收缩,以使表格能够适应其父容器的大小。
    • Stretchable:如果一个列被标识为Stretchable,则该列的宽度可以进行拉伸,以使填满表格中的空闲空间。
    • Collapsed:如果一个列被标识为Collapsed,则该列会被隐藏。

    注意:一个列可以同时具有Shrinkable属性和Stretchable属性,在这种情况下,该列的宽度将任意拉伸或收缩以适应父容器。

    TableLayout继承自LinearLayout类,除了继承来自父类的属性和方法,TableLayout类中还包含表格布局所特有的属性和方法,如下表:

    属性名称 对应方法 描述
    android:collapseColumns setColumnCollapsed(int,boolean) 设置指定列号的列属性为Collapsed
    android:shrinkColumns setShrinkAllColumns(boolean) 设置指定列号的列属性为Shrinkable
    android:stretchColumns setStretchAllColumns(boolean) 设置指定列号的列属性为Stretchable

    注意:TableLayout中所谓的列序号是从0开始计算的。setShrinkAllColumns和setStretchAllColumns实现的功能是将表格中的所有列设置为Shrinkable或Stretchable。

    总结

    有多少个TableRow对象就有多少行,

    列数等于最多子控件的TableRow的列数

    直接在TableLayout加控件,控件会占据一行

    TableLayout属性(也叫全局属性):*代表所有列

    android:shrinkColumns -------设置可收缩的列,(内容过多,则收缩,扩展到第二行,控件没布满TableLayout时不起作用)

    android:stretchColumns ------设置可伸展的列,(有空白则填充)

    列可以同时具备stretchColumns及shrinkColumns属性

    android:collapseColumns ------设置要隐藏的列(索引列从0开始)

    内部控件属性:

    android:layout_column -------该单元格在第几列显示

    android:layout_span -------该单元格占据列数,默认为1

    参考链接https://www.cnblogs.com/tinyphp/p/3812486.html

    帧布局管理器FrameLayout

    帧布局或叫层布局,从屏幕左上角按照层次堆叠方式布局,后面的控件覆盖前面的控件。

    常用属性:

    属性 说明
    layout_gravity 用来设置自身相对于父元素的布局,这个属性在FrameLayout布局时会经常使用到,用来控制控件在布局中的位置,layout_gravity常用属性值有top、bottom、left、right、center、center_horizontal、center_vertical,这里的center可以让控件居于FrameLayout的中心布局,属性值可以复合使用,比如我们既要居底部布局又要垂直居中就可以这样设置:“android:layout_gravity=bottom|center_vertical

    android:foreground表示:设置该帧布局容器的前景图像;
    android:foregroundGravity表示:设置前景图像的显示位置;
    foregroundGravity常用属性值及描述如下:

    属性值 描述
    top 将视图放到屏幕的顶端
    Buttom 将视图放到屏幕的底端
    Left 将视图放在屏幕的左侧
    Right 将视图放在屏幕的右侧
    Center_vertical 将视图按照垂直方向居中显示
    horizontal_vertical 将视图按照水平方向居中显示

    前景图像是什么?
    答:永远处于帧布局最上面,直接面对用户的图像,就是永远不会被覆盖的图像;

    相对布局管理器RelativeLayout

    相对布局常用属性:

    子类控件相对子类控件:值是另外一个控件的id

    android:layout_above----------位于给定DI控件之上
    android:layout_below ----------位于给定DI控件之下

    android:layout_toLeftOf -------位于给定控件左边
    android:layout_toRightOf ------位于给定控件右边

    android:layout_alignLeft -------左边与给定ID控件的左边对齐
    android:layout_alignRight ------右边与给定ID控件的右边对齐
    android:layout_alignTop -------上边与给定ID控件的上边对齐
    android:layout_alignBottom ----底边与给定ID控件的底边对齐

    android:layout_alignBaseline----对齐到控件基准线

    android:layout_above="@id/xxx" --将控件置于给定ID控件之上
    android:layout_below="@id/xxx" --将控件置于给定ID控件之下

    android:layout_toLeftOf="@id/xxx" --将控件的右边缘和给定ID控件的左边缘对齐
    android:layout_toRightOf="@id/xxx" --将控件的左边缘和给定ID控件的右边缘对齐

    android:layout_alignLeft="@id/xxx" --将控件的左边缘和给定ID控件的左边缘对齐
    android:layout_alignTop="@id/xxx" --将控件的上边缘和给定ID控件的上边缘对齐
    android:layout_alignRight="@id/xxx" --将控件的右边缘和给定ID控件的右边缘对齐
    android:layout_alignBottom="@id/xxx" --将控件的底边缘和给定ID控件的底边缘对齐
    android:layout_alignParentLeft=“true” --将控件的左边缘和父控件的左边缘对齐
    android:layout_alignParentTop=“true” --将控件的上边缘和父控件的上边缘对齐
    android:layout_alignParentRight=“true” --将控件的右边缘和父控件的右边缘对齐
    android:layout_alignParentBottom=“true” --将控件的底边缘和父控件的底边缘对齐
    android:layout_centerInParent=“true” --将控件置于父控件的中心位置
    android:layout_centerHorizontal=“true” --将控件置于水平方向的中心位置
    android:layout_centerVertical=“true” --将控件置于垂直方向的中心位置

    相对父容器,值是true或false
    android:layout_alignParentLeft ------相对于父靠左
    android:layout_alignParentTop-------相对于父靠上
    android:layout_alignParentRight------相对于父靠右
    android:layout_alignParentBottom —相对于父靠下

    android:layout_centerInParent=“true” -------相对于父即垂直又水平居中
    android:layout_centerHorizontal=“true” -----相对于父即水平居中
    android:layout_centerVertical=“true” --------相对于父即处置居中

    相对于父容器位置:

    android:layout_margin=“10dp”
    android:layout_marginLeft
    android:layout_marginRight
    android:layout_marginTop
    android:layout_marginBottom

    版本4.2以上相对布局新属性

    android:layout_alignStart---------------------将控件对齐给定ID控件的头部
    android:layout_alignEnd----------------------将控件对齐给定ID控件的尾部
    android:layout_alignParentStart--------------将控件对齐到父控件的头部
    android:layout_alignParentEnd---------------将控件对齐到父控件的尾部

    android:layout_marginLeft指该控件距离边父控件的边距,

    android:paddingLeft指该控件内部内容,如文本距离该控件的边距。

    参考链接:https://blog.csdn.net/loongembedded/article/details/35569043

    题目记录

    1. 线性布局管理器方向属性是 D

    A.direction

    B.trend

    C.orention

    D.orientation

    1. 对齐的属性是 B
    • A.bring
    • B.gravity1.00/1.00
    • C.algin
    • D.justify
    1. layout_width的含义是 D
    • A.设置组件内容的宽度
    • B.组件距原点的距离
    • C.与父组件的宽度比例
    • D.设置本组件的基本宽度
    1. 给线性布局设置颜色要使用 D
    • A.paint属性
    • B.RGB属性
    • C.color属性
    • D.background属性
    1. 表格布局的collapseColumnn属性 B
    • A.可以让某些列失效
    • B.可以让某些例不可见1.00/1.00
    • C.可以删除某些列
    • D.可以合并某些列
    1. 表格布局中允许某些列收缩的属性是: D
    • A.contractColumn
    • B.neckingColumn
    • C. twitchColumn
    • D.shrinkColumn
    1. 表格布局中允许某些列拉伸的属性是:C
    • A.extendColumn
    • B.tensionColumn
    • C.stretchColumn1.00/1.00
    • D.expendColumn
    1. 给框架(帧)布局设置前景图像的属性是 D
    • A.topImage
    • B.frontImage
    • C.firstImage
    • D.foreground
    1. 框架(帧)布局的特点是 D
    • A.会自动对齐到中心
    • B.会忽略原点(左上角)
    • C.多个帧会平铺布置
    • D.后面的布局覆盖前面的
    1. 对于约束布局下列说明正确的是 B
    • A.AndroidStudio创建项目无法同时创建约束布局
    • B.约束布局是相对布局的改进版1.00/1.00
    • C.是借鉴了WindowsPhone研发的
    • D.约束布局只能用绝对的数值去调整组件位置
    展开全文
  • Android 布局优化方案

    万次阅读 2020-12-28 15:45:31
    Android 开发中,UI 布局可以说是每个 App 使用频率很高的,随着 UI 越来越多,布局的重复性、复杂度也会随之增长,这样使得 UI布局的优化,显得至关重要,UI 布局不慎,就会引起过度绘制,从而造成 UI 卡顿的...

    前言

    在 Android 开发中,UI 布局可以说是每个 App 使用频率很高的,随着 UI 越来越多,布局的重复性、复杂度也会随之增长,这样使得 UI布局的优化,显得至关重要,UI 布局不慎,就会引起过度绘制,从而造成 UI 卡顿的情况,本篇文章就来总结一下 UI 布局优化的相关技巧。

    说明: 本文的源码都是基于 Android API 30 进行分析。

    一、布局优化标签的使用

    1.1 <include> 标签

    include 标签常用于将布局中的公共部分提取出来供其他 layout 共用,以实现布局模块化,这在布局编写方便提供了大大的便利。

    我们项目的 UI 中很多页面都会有一个TitleBar 部分,所以使用 <include> 标签进行复用,以便于统一管理,

    我们写一个TitleBar (title_bar_layout.xml) ,代码如下所示:

    <?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="50dp">
    ​
        <ImageView
            android:id="@+id/iv_back"
            android:layout_width="50dp"
            android:layout_height="match_parent"
            android:padding="15dp"
            android:src="@drawable/back" />
    ​
        <TextView
            android:id="@+id/tv_title"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:layout_toRightOf="@+id/iv_back"
            android:layout_toLeftOf="@+id/tv_sure"
            android:gravity="center"
            android:text="我是标题"
            android:textSize="16sp" />
    ​
        <TextView
            android:id="@+id/tv_sure"
            android:layout_width="50dp"
            android:layout_height="match_parent"
            android:gravity="center"
            android:layout_alignParentRight="true"
            android:text="确定"
            android:textSize="16sp" />
    </RelativeLayout>

    然后我们在 activity_main.xml 中使用 <include> 标签引入上面定义的 TitleBar 布局,代码如下是所示:

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">
    ​
        <include
            layout="@layout/title_bar_layout" />
    ​
        <View
            android:id="@+id/view_head_line"
            android:layout_width="match_parent"
            android:layout_height="1px"
            android:layout_marginTop="50dp"
            android:background="@color/black" />
    ​
        <TextView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_below="@+id/view_head_line"
            android:gravity="center"
            android:text="我是内容" />
    </RelativeLayout>

    运行效果如下图所示:

     

    <include> 标签唯一需要的属性是 layout 属性,用来指定需要包含的布局文件。也可以定义 android:id 和 android:layout_* 属性来覆盖被引入布局根节点的对应属性值。

    注意的问题

    使用 <include> 最常见的问题就是 findViewById 查找不到目标控件,这个问题出现的前提是在 <include> 标签中设置了 android:id 属性导致子布局根节点的 android:id失效了,而在 findViewById 时却用了被 <include> 进来的布局的根元素 android:id 中设置的值。

    例如上述例子中,设置 TitleBar (title_bar_layout.xml) 的根节点的 android:id 属性值为 child_title_bar,代码如下所示:

    <?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="50dp"
        android:id="@+id/child_title_bar">
        // 里面的内容省略,更上面提供的布局一样。
        // ...
    </RelativeLayout>

    然后在 activity_main.xml 中通过 <include> 应用TitleBar 子布局,然后设置 android:id 属性为 mian_title_bar,代码如下所示:

    <include
        android:id="@+id/main_title_bar"
        layout="@layout/title_bar_layout" />

    此时如果通过 findViewById 来找 child_title_bar 这个控件,然后再查找 child_title_bar 下的子控件则会抛出空指针。代码如下 :

    // 此时 titleBar 为空,找不到
    View titleBar = findViewById(R.id.child_title_bar);
    // 此时空指针
    TextView tvTitle = titleBar.findViewById(R.id.tv_title);
    tvTitle.setText("new Title");

    其正确的使用形式应该如下:

    View titleBar = findViewById(R.id.main_title_bar);
    TextView tvTitle = titleBar.findViewById(R.id.tv_title);
    tvTitle.setText("new Title");

    或者更简单的直接查找他的子控件

    TextView tvTitle = findViewById(R.id.tv_title);
    tvTitle.setText("new Title");

    但是当 activity_main.xml 中有多个 <include> 标签时,而且标签中有相同的 android:id 属性值时,就不能使用上述简单的直接查找方式了。如果直接通过 android:id 属性值去查找子控件的话,他是查到到第一个 <include> 应用的布局中的子控件。

    验证:

    我们把 activity_main.xml 修改为以下形式:

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">
    ​
        <include
            layout="@layout/title_bar_layout" />
    ​
        <View
            android:id="@+id/view_head_line"
            android:layout_width="match_parent"
            android:layout_height="1px"
            android:layout_marginTop="50dp"
            android:background="@color/black" />
    ​
        <TextView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_below="@+id/view_head_line"
            android:layout_above="@+id/view_foot_line"
            android:gravity="center"
            android:text="我是内容" />
    ​
        <View
            android:id="@+id/view_foot_line"
            android:layout_width="match_parent"
            android:layout_height="1px"
            android:layout_alignParentBottom="true"
            android:layout_marginBottom="50dp"
            android:background="@color/black" />
    ​
        <include
            layout="@layout/title_bar_layout"
            android:layout_height="50dp"
            android:layout_width="match_parent"
            android:layout_alignParentBottom="true"/>
    </RelativeLayout>

    然后在 MainActivity 中使用直接查找的方式使用控件,代码如下所示:

    public class MainActivity extends Activity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            
            TextView tvTitle = findViewById(R.id.tv_title);
            tvTitle.setText("new Title");
        }
    }

    运行结果如下所示:

     

    我们发现只有第一个 <include> 标签中 tv_title 修改了。

    所以,多个 <include> 标签的正确使用方法是,每个 <include> 标签都设置 android:id 属性,然后查找的时候根据 <include> 中设置的 android:id 属性值找到它应用的子布局的跟节点,再根据根节点查找根节点的子控件,代码如下所示:

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">
    
        <include
            android:id="@+id/head_title_bar"
            layout="@layout/title_bar_layout" />
    
        <View
            android:id="@+id/view_head_line"
            android:layout_width="match_parent"
            android:layout_height="1px"
            android:layout_marginTop="50dp"
            android:background="@color/black" />
    
        <TextView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_above="@+id/view_foot_line"
            android:layout_below="@+id/view_head_line"
            android:gravity="center"
            android:text="我是内容" />
    
        <View
            android:id="@+id/view_foot_line"
            android:layout_width="match_parent"
            android:layout_height="1px"
            android:layout_alignParentBottom="true"
            android:layout_marginBottom="50dp"
            android:background="@color/black" />
    
        <include
            android:id="@+id/foot_title_bar"
            layout="@layout/title_bar_layout"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:layout_alignParentBottom="true" />
    </RelativeLayout>
    public class MainActivity extends Activity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            View headTitleBar = findViewById(R.id.head_title_bar);
            TextView tvHeadTitle = headTitleBar.findViewById(R.id.tv_title);
            tvHeadTitle.setText("new head Title");
    
            View footTitleBar = findViewById(R.id.foot_title_bar);
            TextView tvFootTitle = footTitleBar.findViewById(R.id.tv_title);
            tvFootTitle.setText("new foot Title");
        }
    }

    运行结果如下:

     

    下面我们分析 <include> 设置了 android:id 属性,然后我们在使用 findViewById 传入子布局中根节点设置的android:id 时,找不到根节点的原因。

    对于布局文件的解析,最总都会调用到 LayoutInflater 的 inflate 方法,该方法最终又会调用 RInflate 方法,我们就从这个方法开始分析。

    rInflate 方法代码如下所示:

    void rInflate(XmlPullParser parser, View parent, Context context,
            AttributeSet attrs, boolean finishInflate) throws XmlPullParserException, IOException {
    
        final int depth = parser.getDepth();
        int type;
        boolean pendingRequestFocus = false;
    
        while (((type = parser.next()) != XmlPullParser.END_TAG ||
                parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) {
    
            if (type != XmlPullParser.START_TAG) {
                continue;
            }
    
            final String name = parser.getName();
    
            if (TAG_REQUEST_FOCUS.equals(name)) {
                pendingRequestFocus = true;
                consumeChildElements(parser);
            } else if (TAG_TAG.equals(name)) {
                parseViewTag(parser, parent, attrs);
            } else if (TAG_INCLUDE.equals(name)) {
                if (parser.getDepth() == 0) {
                    throw new InflateException("<include /> cannot be the root element");
                }
                // ... 2
                parseInclude(parser, context, parent, attrs);
            } else if (TAG_MERGE.equals(name)) {
                throw new InflateException("<merge /> must be the root element");
            } else {
                // ... 1
                final View view = createViewFromTag(parent, name, context, attrs);
                final ViewGroup viewGroup = (ViewGroup) parent;
                final ViewGroup.LayoutParams params = viewGroup.generateLayoutParams(attrs);
                rInflateChildren(parser, view, attrs, true);
                viewGroup.addView(view, params);
            }
        }
    
        if (pendingRequestFocus) {
            parent.restoreDefaultFocus();
        }
    
        if (finishInflate) {
            parent.onFinishInflate();
        }
    }

    这个方法其实就是遍历 xml 中的所有元素,然后挨个进行解析,例如解析到一个控件类型的标签,就会通过注释1处的代码,根据用户设置的 layout_*、andriod:id 、android:backage 等属性来够着一个 View 对象,然后添加到它的父控件(ViewGroup)中。<include> 标签也是一样,就会通过注释2处代码来解析 <include> 标签,主要是通过 parseInclude 方法解析,代码如下所示:

    private void parseInclude(XmlPullParser parser, Context context, View parent,
                              AttributeSet attrs) throws XmlPullParserException, IOException {
        int type;
    
        //  <include> 标签必须使用在 ViewGroup 中
        if (!(parent instanceof ViewGroup)) {
            throw new InflateException("<include /> can only be used inside of a ViewGroup");
        }
    
        // ......
    
        // <include> 标签中必须要设置 layout 属性,否则会抛出异常。
        if (layout == 0) {
            final String value = attrs.getAttributeValue(null, ATTR_LAYOUT);
            throw new InflateException("You must specify a valid layout "
                    + "reference. The layout ID " + value + " is not valid.");
        }
    
        final View precompiled = tryInflatePrecompiled(layout, context.getResources(),
                (ViewGroup) parent, /*attachToRoot=*/true);
        if (precompiled == null) {
            final XmlResourceParser childParser = context.getResources().getLayout(layout);
    
            try {
                final AttributeSet childAttrs = Xml.asAttributeSet(childParser);
    
                while ((type = childParser.next()) != XmlPullParser.START_TAG &&
                        type != XmlPullParser.END_DOCUMENT) {
                    // Empty.
                }
    
                if (type != XmlPullParser.START_TAG) {
                    throw new InflateException(getParserStateDescription(context, childAttrs)
                            + ": No start tag found!");
                }
                // 解析 <include> 应用的子布局中的第一个元素
                final String childName = childParser.getName();
    
                // 如果第一个元素是 <merge> 标签,那么调用 rInflate 方法解析
                if (TAG_MERGE.equals(childName)) {
                    // The <merge> tag doesn't support android:theme, so
                    // nothing special to do here.
                    rInflate(childParser, parent, context, childAttrs, false);
                } else {
                    // 我们例子中的情况会走到这一步,首先根据 include 的属性集创建被 include 进来的xml布局的根 view
                    // 这里的根 view 对应为 title_bar_layout.xml中的 LinearLayout
                    final View view = createViewFromTag(parent, childName,
                            context, childAttrs, hasThemeOverride);
                    final ViewGroup group = (ViewGroup) parent;
    
                    final TypedArray a = context.obtainStyledAttributes(
                            attrs, R.styleable.Include);
                    // 获取 <include> 标签中设置的 id。
                    final int id = a.getResourceId(R.styleable.Include_id, View.NO_ID);
                    final int visibility = a.getInt(R.styleable.Include_visibility, -1);
                    a.recycle();
    
                    // We try to load the layout params set in the <include /> tag.
                    // If the parent can't generate layout params (ex. missing width
                    // or height for the framework ViewGroups, though this is not
                    // necessarily true of all ViewGroups) then we expect it to throw
                    // a runtime exception.
                    // We catch this exception and set localParams accordingly: true
                    // means we successfully loaded layout params from the <include>
                    // tag, false means we need to rely on the included layout params.
                    ViewGroup.LayoutParams params = null;
                    try {
                        // 获取布局属性
                        params = group.generateLayoutParams(attrs);
                    } catch (RuntimeException e) {
                        // Ignore, just fail over to child attrs.
                    }
                    if (params == null) {
                        params = group.generateLayoutParams(childAttrs);
                    }
                    view.setLayoutParams(params);
    
                    // Inflate all children. 解析所有的子控件
                    rInflateChildren(childParser, view, childAttrs, true);
    
                    // 如果 <include> 中设置了 id,就将此 id 设置给 include 子布局的根节点。
                    if (id != View.NO_ID) {
                        view.setId(id);
                    }
    
                    switch (visibility) {
                        case 0:
                            view.setVisibility(View.VISIBLE);
                            break;
                        case 1:
                            view.setVisibility(View.INVISIBLE);
                            break;
                        case 2:
                            view.setVisibility(View.GONE);
                            break;
                    }
                    // 将 include 进来的根节点加入到ViewGroup 中。
                    group.addView(view);
                }
            } finally {
                childParser.close();
            }
        }
        LayoutInflater.consumeChildElements(parser);
    }

    所以结论就是: 如果 <include> 标签中设置了andrid:id属性,那么就通过 <include> 标签中设置 android:id 属性值来查找被 include 布局根元素的 View;如果 <include> 标签中没有设置 android:id 属性, 而被 include 的布局的根元素设置了 android:id 属性,那么通过该根元素的 id 来查找该 View 即可。拿到根元素后查找其子控件都是一样的。

    1.2 <merge> 标签

    <merge> 标签主要用户辅助 <include> 标签,在使用 <include> 标签之后可能导致布局嵌套过多,多余的 layout 节点会导致解析变慢,不必要的节点和嵌套可以通过 Layout Inspector (下面会介绍) 或者通过设置中的显示布局边界查看,还可以通过 hierarchy viewer 查看布局边界,但是 hierarchy viewer 已经弃用,如果使用的是Android Studio 3.1 或更高版本,则应在运行时改用布局检查器以检查应用的视图层次结构。如需分析应用布局的渲染速度,请使用 Window.OnFrameMetricsAvailableListener**。

    <merge> 标签可用于两种典型的情况:

    (1) 布局根节点是 FrameLayout 且不需要设置 background 或者 padding 等属性,可以用 <merge> 标签代替,因为 Activity 内容视图的 parent View 就是一个 FrameLayout ,所以可以使用 <merge> 标签消除一个,减少布局嵌套,降低过度绘制。

    (2) 某布局作为子布局被其他布局 include 时,使用merge当做该布局的根节点,这样在被引入时根节点就会自动被忽略,而将其子节点全部合并到主布局中。

    还是以上面 TitleBar (title_bar_layout.xml)布局为例,在 activity_mian.xml 引用如下所示:

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">
    
        <include
            android:id="@+id/head_title_bar"
            layout="@layout/title_bar_layout" />
    
        <View
            android:id="@+id/view_head_line"
            android:layout_width="match_parent"
            android:layout_height="1px"
            android:layout_marginTop="50dp"
            android:background="@color/black" />
    
        <TextView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_below="@+id/view_head_line"
            android:gravity="center"
            android:text="我是内容" />
        
    </RelativeLayout>

    运行之后,我们通过 Layout Inspector 查看 activity_mian 布局如下图所示:

     

    可以发现多了一层没有必要的 RelativeLayout ,将 TitleBar (title_bar_layout.xml) 中的 RelativeLayout 替换为 merge ,代码如下所示:

    title_bar_layout.xml

    当使用了 <merge> 标签之后,子控件的宽高如果使用 match_parent 属性时,它是相对于 <include> 的父控件 ViewGroup 来配置的。

    <?xml version="1.0" encoding="utf-8"?>
    <merge xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:id="@+id/child_title_bar">
    
        <ImageView
            android:id="@+id/iv_back"
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:padding="15dp"
            android:src="@drawable/back" />
    
        <TextView
            android:id="@+id/tv_title"
            android:layout_width="0dp"
            android:layout_height="50dp"
            android:layout_weight="1"
            android:layout_toRightOf="@+id/iv_back"
            android:layout_toLeftOf="@+id/tv_sure"
            android:gravity="center"
            android:text="我是标题"
            android:textSize="16sp" />
    
        <TextView
            android:id="@+id/tv_sure"
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:gravity="center"
            android:layout_alignParentRight="true"
            android:text="确定"
            android:textSize="16sp" />
    </merge>

    再次运行之后,我们通过 Layout Inspector 查看 activity_mian 布局如下图所示:

     

    使用 <merge> 标签需要注意一下几点:

    1. 因为 <merge> 并不是 View ,所以在通过 LayoutInflate.inflate() 方法渲染的时候,第二个参数必须指定一个父容器,而且第三个参数必须设置为 true ,也就是必须为 <merge> 下的视图指定一个父节点。

    2. 因为 <merge> 并不是View,所以在 <merge> 中设置的所有属性都是无效的。

    3. <merge> 标签必须使用在根布局。

    4. <ViewStub> 标签中的 layout 布局不能使用 <merge> 标签。

    1.3 <ViewStub> 标签

    <ViewStub> 标签与 <include> 标签一样可以用来引入一个外部布局,不同的是,<ViewStub> 引入的布局默认不会扩张,既不会占用显示也不会占用位置,从而在解析 layout 文件时节省 CPU 和 内存。

    <ViewStub> 标签最大的优点是当需要时才会加载,使用它并不会影响 UI 初始化时的性能,各种不常用的布局像进度条、网络错误等都可以使用 <ViewStub> 标签,以减少内存的使用,加快渲染速度, <ViewStub> 是一个不可见的,实际上是把宽高设置为0的 View 。

    官方文档:

    https://developer.android.google.cn/training/improving-layouts/loading-ondemand.html

    下面我们以显示网络错误提示页面为例来分析 <ViewStub> 标签的使用。

    我们新建一个 network_error.xml 布局 ,代码如下所示:

    <?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:id="@+id/root_network_error"
        android:gravity="center">
    
        <ImageView
            android:id="@+id/iv_network_error"
            android:layout_width="150dp"
            android:layout_height="150dp"
            android:src="@drawable/network_error" />
    
        <Button
        	android:id="@+id/btn_reload"
            android:layout_width="150dp"
            android:layout_height="wrap_content"
            android:layout_below="@+id/iv_network_error"
            android:layout_marginTop="20dp"
            android:text="重新加载" />
    </RelativeLayout>

    在 activity_main.xml 通过 <ViewStub> 标签引用 network_error 布局,代码如下所示:

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">
    
        <Button
            android:id="@+id/btn_show_network_error"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:text="显示网络异常提示" />
    
        <Button
            android:id="@+id/btn_hide_network_error"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_marginRight="10dp"
            android:text="隐藏网络异常提示" />
    
        <ViewStub
            android:id="@+id/vs_network_error"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_below="@+id/btn_hide_network_error"
            android:layout="@layout/network_error" />
    
    </RelativeLayout>

    在 MainActivity 中通过 findViewById(vs_network_error) 找到 ViewStub,通过stub.inflate() 展开 ViewStub,然后得到子 View,如下:

    public class MainActivity extends Activity implements View.OnClickListener {
        private View networkErrorView;
        private ViewStub viewStub;
        private Button btnReload;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            viewStub = findViewById(R.id.vs_network_error);
    
            findViewById(R.id.btn_show_network_error).setOnClickListener(this);
            findViewById(R.id.btn_hide_network_error).setOnClickListener(this);
        }
    
    
        @Override
        public void onClick(View v) {
            switch (v.getId()) {
                case R.id.btn_show_network_error:
                    showNetworkError();
                    break;
                case R.id.btn_hide_network_error:
                    hideNetworkError();
                    break;
                case R.id.btn_reload:
                    Toast.makeText(this, "重新加载", Toast.LENGTH_SHORT).show();
                    break;
            }
        }
    
    
        public void showNetworkError() {
            // networkErrorView == null 的时候表示还没调用 ViewStub 的 inflate 方法。
            if (networkErrorView == null && viewStub != null) {
                // 调用 ViewStub 的 inflate 方法渲染 View,这个方法只用调用一次即可,
                // 说明:当调用了 ViewStub 的 inflate 方法之后,ViewStub 的内容就会展开。
                // 在需要的时候在调用,减少 xml 解析时间,节省内存
                // 这里获取的 networkErrorView 就是 <ViewStub> 标签引用布局的额根节点(这里是 RelativeLayout )
                networkErrorView = viewStub.inflate();
                btnReload = networkErrorView.findViewById(R.id.btn_reload);
                btnReload.setOnClickListener(this);
            }
            if (networkErrorView != null) {
                networkErrorView.setVisibility(View.VISIBLE);
            }
        }
    
        public void hideNetworkError() {
            if (networkErrorView != null) {
                networkErrorView.setVisibility(View.GONE);
            }
        }
    }

    在上面 showNetworkError() 中展开了 ViewStub,同时我们对 networkErrorView 进行了保存,这样下次不用继续 inflate,减少不必要的 infalte 。

    上面展开 ViewStub 部分代码如下:

    viewStub = findViewById(R.id.vs_network_error);
    networkErrorView = viewStub.inflate(); // 展开 ViewStub布局,并返回其引用布局的根节点

    也可以写成下面的形式:

    viewStub = findViewById(R.id.vs_network_error);
    viewStub.setVisibility(View.VISIBLE);// 展开ViewStub布局
    networkErrorView = findViewById(R.id.root_network_error);// 获取ViewStub引用布局的根节点

    注意

    1. 这里我对 ViewStub 的实例进行了一个非空判断,这是因为 ViewStub 在 XML 中定义的 id 只在一开始有效,一旦 ViewStub 中指定的布局加载之后,这个 id 也就失效了,那么此时 findViewById() 得到的值也会是空。

    2. View 的可见性设置为 gone 后,在 inflate 时,这个View 及其子 View 依然会被解析的。使用 ViewStub 就能避免解析其中指定的布局文件,从而节省布局文件的解析时间,及内存的占用。

    二、布局调优工具

    2.1 Layout Inspector

    使用 Android Studio 中的布局检查器,您可以将应用布局与设计模型进行比较、显示应用的放大视图或 3D 视图,以及在运行时检查应用布局的细节。如果布局是在运行时(而不是完全在 XML 中)构建的并且布局行为出现异常,该工具会非常有用。

    使用布局验证,您可以在不同的设备和显示配置(包括可变字体大小或用户语言)上同时预览布局,以便轻松测试各种常见的布局问题。

    下面基于 Android Studio 4.1.1 分析 Layout Inspector 的基本使用。

    1. 打开Layout Inspector

    (1) 在连接的设备或模拟器上运行应用。

    (2) 一次点击 Tools -> Layout Inspector。

    (3) 在显示的 Layout Inspector 对话框中,选择想要检查的应用进程。

     

     

    Layout Inspector 显示内容说明

    视图层次结构(Component Tree):显示当前界面的布局层次结构,支持折叠、收起、选中、右键调试视图等。

    工具栏:调试进程选择,视图边界,实时更新等。

    屏幕截图(Layout Display):按照应用布局在设备或模拟器上的显示效果呈现布局,并显示每个视图的布局边界。支持点击选中视图、右键调整视图、放大/缩小视图、3D视角等。

    布局属性(Attributes):所选视图的布局属性。

    2. 选择视图

    如要选择某个视图,请在 Component TreeLayout Display 中点击该视图。所选视图的所有布局属性都会显示在 Attributes 面板中。

    如果布局包含重叠的视图,您可以选择不在最前面的视图,方法是在 Component Tree 中点击该视图,或者旋转布局(3D视图)并点击所需视图。

    3. 隐藏布局边界 & 隐藏布局模板

     

    Show Borders:显示/隐藏 布局的边界(也就是 View 的区域边界线),就像我们在开发者模式中打开了 View 绘制边界 一样。

    Show View Label:显示布局的布局标签,比如上图的 "tvl" 它的布局标签就是TextView

    4. 将应用布局与参考图叠加层进行比较

    如需将应用布局与参考图像(如界面模型)进行比较,您可以在布局检查器中加载位图图像叠加层。

    • 如需加载叠加层,请点击布局检查器顶部的 Load Overlay 图标 。系统会缩放叠加层以适合布局。

    • 如需调整叠加层的透明度,请使用 Overlay Alpha 滑块。

    • 如需移除叠加层,请点击 Clear Overlay 图标

    5. 实时布局检查器

    实时布局检查器可以在应用被部署到搭载 API 级别 29 或更高版本的设备或模拟器时,提供应用界面的完整实时数据分析

    如需启用实时布局检查器,请依次转到 File > Settings > Experimental,勾选 Enable Live Layout Inspector 旁边的框,然后点击 Layout Display 上方 Live updates 旁边的复选框。如下图所示:

     

    实时布局检查器包含动态布局层次结构,可随着设备上视图的变化更新 Component TreeLayout Display

    此外,使用属性值解析堆栈,您可以调查资源属性值在源代码中的来源位置,并按照属性窗格中的超链接导航到其位置。如下图所示:

     

    6. 3D视图

    这个看起来很酷炫,可是很遗憾,我的设备并不支持。

     

    3D 视图查看需要 API >= 29 .

    下面摘抄 Google 官方文档描述3D视图的使用。

    Layout Display 可在运行时对应用的视图层次结构进行高级 3D 可视化。如需使用该功能,只需在实时布局检查器窗口中点击相应布局,然后拖动鼠标旋转该布局即可。如需展开或收起布局的图层,请使用 Layer Spacing 滑块。

     

    2.2 调试GPU过度绘制(Overdraw)

    UI界面被多次不必要的重绘,就叫 overdraw。这是对 GPU 的浪费,在低端手机还有可能造成界面卡顿。

    1. 如何检测是否发生了 overdraw

    (1)在您的设备上,转到 Settings(设置) 并选择 Developer Options(开发者选项)。

    (2)向下滚动到 Hardware accelerated rendering (硬件)部分,并选择 Debug GPU Overdraw(调试 GPU 过度绘制)。

    (3) 在 Debug GPU overdraw (调试 GPU 过度绘制)对话框中,选择 Show overdraw areas(展示过度绘制区域)。

    然后查看你的UI页面是否有下面的颜色块,不同颜色代表不同的绘制次数

     

    2. overdraw 解决办法

    • 移除不必要的 background,这是一种快速提升渲染性能的方式。

    • 减少布局层级。

    • 减少使用透明视图。

    2.3 Hierarchy Viewer

    Hierarchy Viewer 工具提供了一个可视化界面显示布局的层次结构,让我们可以进行调试,从而优化界面布局结构。

    由于 Google 已经弃用该工具,这里就不做讲解,想了解的同学可以通过 Google 官方文档查看其使用教程。

    https://developer.android.google.cn/studio/profile/hierarchy-viewer.html

    2.4 Lint

    Android Studio 提供了一个名为 lint 的代码扫描工具,可帮助您发现并更正代码结构质量的问题,而无需您实际执行应用,也不必编写测试用例。系统会报告该工具检测到的每个问题并提供问题的描述消息和严重级别,以便您可以快速确定需要优先进行的关键改进。此外,您还可以降低问题的严重级别以忽略与项目无关的问题,或者提高严重级别以突出特定问题。

    这个工具也可以用来检测布局中存在的问题。

    Google 官方文档地址:https://developer.android.google.cn/studio/write/lint?hl=zh_cn

    扫描下方二维码关注公众号,获取更多技术干货。

     

    展开全文
  • Android布局的优化

    千次阅读 2016-04-29 11:46:55
    在Android开发中,我们常用的布局方式主要有LinearLayout、RelativeLayout、FrameLayout等,通过...本篇内容就主要围绕Android布局优化来讨论在日常开发中我们使用常用布局需要注意的一些方面,同时介绍一款SDK自带的U
  • Android布局之线性布局

    千次阅读 2017-09-06 22:06:10
    第一节介绍了新建Android项目时默认生成的布局文件,默认的布局文件采用的相对布局RelativeLayout,在这个布局中也默认添加了一个TextView控件。本节讲的这个LinearLayout线性布局和RelativeLayout相对布局类似,同...
  • android布局及常见布局属性

    千次阅读 2011-08-10 13:56:20
    android布局方式 Android对用五大布局对象 FrameLayout LinearLayout RelativeLayout TableLayout AbsoluteLayout FrameLayout FrameLayout是最简单的一个布局对象。
  • Android布局背景颜色设置

    千次阅读 2017-04-14 16:43:52
    安卓开发,背景色原文地址:Android布局背景颜色设置作者:jxfzhwp在java或android程序中,用到颜色信息的时候,一般并不直接给定颜色信息而是用字符串来表示, 比如我们通常用下面的语句来设置布局的背景颜色 ...
  • Android 布局中 如何使控件居中

    万次阅读 2016-03-03 22:23:08
    Android 布局中如何使控件居中 首先要分两种不同情况,在两种不同的布局方式下:LinearLayout 和RelativeLayout 1. LinearLayout a). android:layout_gravity="center_horizontal"表示该布局在父布局里水平居中,...
  • [置顶] Android布局管理器 - 详细解析布局实现 http://blog.csdn.net/shulianghan/article/details/17226581 分类: android基础 2013-12-13 00:01 2177人阅读 评论(18) 收藏 举报 布局线性布局绝对布局...
  • Android 布局生成分享图片

    千次阅读 2018-01-13 16:36:38
    Android 布局生成分享图片 先看图   首先, 第一次写博客,也不知道说点什么。写的不好的地方希望大家能理解一下! 然后,说一说自己的艰苦过程!因为没有写过这个功能,而公司又强需此功能,我也只好...
  • android布局与计算器app编程

    千次阅读 2016-07-07 19:14:14
    android布局、计算器app...
  • Android布局属性android:clipToPadding的UI设计妙用 一个简单的UI效果场景。顶部一个半透明Toolbar,然后下面是一个ListView,要求ListView在初始状态下(即未触发任何滑动事件情况下)的item全部在Toolbar下面...
  • Android布局优化 merge标签使用

    千次阅读 2016-02-25 23:50:30
    复杂的界面布局往往会因为层次...标签用于减少View的层次来优化Android布局,先写一个布局<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/to
  • Android布局中margin与padding的区别

    万次阅读 多人点赞 2017-08-04 17:20:34
    我们知道Android开发不仅仅有代码的动态控制,而且还涉及到布局的静态搭建(xml)。几乎在每一个xml文件中,我们总会看到margin和padding这两个属性,今天让我们初步探究一下它们之间的区别。...在Android布局中,pad
  • Android布局类型概述

    千次阅读 2011-12-07 21:52:51
    Android布局类型主要有四种,分别是LinearLayout(线性布局)、RelativeLayout(相对布局)、TableLayout(表格布局)、FrameLayout(帧布局)。然后再介绍一下线性布局与相对布局嵌套使用。注:Layout布局文件名...
  • Android 布局组件

    千次阅读 2016-07-31 14:56:02
     布局用于定义Activity中UI元素的排列结构,Android提供了LinearLayout线性布局、RelativeLayout相对布局 、FrameLayout帧布局 、TableLayout表格布局、AbsoluteLayout坐标布局 共五种布局,可以通过两种方式声明...
  • Android布局之表格布局

    千次阅读 2018-06-09 11:03:02
    TableLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:...
  • 安卓移动开发实验二:Android布局

    万次阅读 2019-03-18 14:38:51
    安卓移动开发实验二:Android布局一、试验内容二、试验代码与截图1.LinearLayout2.ConstraintLayout3.TableLayout 一、试验内容 通过Android studio,分别利用LinearLayout、ConstraintLayout和TableLayout实现老师...
  • Android布局总结四:Merge总结

    千次阅读 2017-09-18 16:57:09
    引言merge标签是作为include标签的一种辅助扩展来使用的,它的主要作用是为了防止在引用布局文件时产生多余的布局嵌套。...include标签的缺点在 Android布局总结三:include总结 我们讲解include标签的用法时主要
  • Android布局之网格布局

    千次阅读 2018-10-21 23:58:30
    1. 什么是布局  就是把界面中的控件按照某种规律摆放到指定的位置 2. 布局的二种实现  代码  xml配置文件:res/layout目录下  注:也可以同时使用xml和代码 3. 布局的基本属性  取值范围  { //效果是一样的 ...
  • Android布局基础知识

    千次阅读 2020-03-21 15:32:27
    UI(User Interface)界面是人与手机之间数据传递的、信息交互的重要媒介和对话窗口,是Android系统的重要组成部分。设计美观的UI界面布局是必不可少的组件。 布局的类型 Linear Layout(线型布局)、Relative Layout ...
  • Android布局经典啊

    千次阅读 2010-10-15 12:36:00
    Android布局 编辑文档 我们对Android应用程序运行原理及布局文件可谓有了比较深刻的认识和理解,并且用“Hello World!”程序来实践证明了。在继续深入Android开发之旅之前,有必要解决前两篇中没有...
  • Android布局查看工具

    千次阅读 2013-04-09 15:37:00
    Android布局查看工具HierarchyViewer,有时候提示连不上view server,可以使用以下方法检验。 检验一台手机是否开启了View Server的办法为: adb shell service call window 3 若返回值是:Result: Parcel...
  • GridLayout布局简介GridLayout布局Android4.0(API Level 14)新引入的网格矩阵形式的布局控件。GridLayout属性介绍本身属性 android:alignmentMode 说明:当设置alignMargins,使视图的外边界之间进行校准。可以...
  • android布局中使用include及需注意点

    万次阅读 2016-08-18 14:25:26
    android布局中,使用include,将另一个xml文件引入,可作为布局的一部分,但在使用include时,需注意以下问题: 一、使用include引入 如现有标题栏布局block_header.xml,代码如下: ...
  • Android布局顶到状态栏or状态栏布局or沉浸式状态栏1.状态栏里面开始布局的设置主题&lt;style name="NoActionBar" parent="Theme.AppCompat.Light.DarkActionBar"&gt; &lt;item ...
  • Android 布局错乱 Android花屏

    千次阅读 2017-06-24 17:33:01
    我先给大家看下什么叫布局错乱,花屏: 来张正常的图片: 正常情况下是这样的。然后,错误的情况下: 全乱了。有的图片都没有显示出来。我说一下复现步骤: 1。打开应用 2。最近任务,一键杀死所有进程。 3。...
  • Android 布局之边框、分割线

    万次阅读 2015-07-27 00:51:51
    Android布局之边框、分割线 http://blog.csdn.net/zapperbot (转) 先上图,实现如下图样式 布局文件使用Linerlayout垂直布局即可,这里省略,主要需要添加如下样式: ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 106,182
精华内容 42,472
关键字:

android布局