文章目录

  • 布局
    • 六大布局 特点
    • 约束布局
    • LinearLayout,RelativeLayout性能对比
    • 检测布局深度
    • 布局优化
      • include、merge、ViewStub标签
  • 面试
    • 你知道布局文件到控件对象的过程吗?(Android布局文件映射源码分析)

布局

六大布局 特点

菜鸟教程
Android知识体系总结之Android部分之Android中的布局篇

布局 介绍 常用属性
LinearLayour
线性布局
LinearLayout容器中的组件一个挨一个排列,通过控制android:orientation属性,可控制各组件是横向排列还是纵向排列 orientation:布局中组件排列方式
gravity:该组件所包含的子元素的对齐方式(horizontal/vertical)
layout_gravity:该组件在父容器里的对齐方式
layout_width:布局的宽度(wrap_content(布局实际大小)/match_parent(填满父容器))
layout_height:布局的高度(参数同上)
layout_weight:布局的权重(需要相应设置layout_height/width=0dp)
RelativeLayout
相对布局
相对布局可以让子控件以其兄弟控件或父控件为参考按照其相对位置进行布局,适用于复杂的嵌套布局 1. 根据父容器定位,如layout_alignParentLeft\Right\Top\Bottom(左\右\顶部\底部对齐)layout_centerHorizontal\Vertical\InParent(水平\垂直\整体居中)
2. 根据兄弟组件定位,如layout_toLeftOf\RightOf\above\below(参考组件左\右\上\下方)layout_alignTop\Bottom\Left\Right(顶部\底部\左\右对齐)
3. margin:偏移,设置该组件与父容器的边距
4. padding:填充,设置组件内部元素间的边距
TableLayout
表格布局
TableLayout继承自Linearout,本质上仍然是线性布局管理器。表格布局采用行、列的形式来管理UI组件
每个TableLayout都是由一个或多个TableRow组成的,一个TableRow就代表TableLayout的一行
(不声明行数、列数。tablerow的个数为表格的行数,tablerow中组件个数为该行的列数)
android:collapseColumns:设置需要被隐藏的列的序号
android:shrinkColumns:设置允许被收缩的列的列序号
android:stretchColumns:设置运行被拉伸的列的列序号
android:layout_column=“2”:表示的就是跳过第二个,直接显示到第三个格子处(从1开始计算)
android:layout_span=“4”:表示合并4个单元格,也就说这个组件占4个单元格
FrameLayout
帧布局
帧布局或叫层布局,从屏幕左上角按照层次堆叠方式布局,后面的控件覆盖前面的控件。帧布局为每个加入其中的组件创建一个空白的区域(称为一帧),每个子组件占据一帧,这些帧会根据gravity属性执行自动对齐 android:foreground:设置改帧布局容器的前景图像
android:foregroundGravity:设置前景图像显示的位置
GridLayout
表格布局
GridLayout把整个容器划分为rows × columns个网格,每个网格可以放置一个组件。提供了setRowCount(int)和setColumnCount(int)方法来控制该网格的行和列的数量 android:orientation:子组件排列方式
android:layout_gravity:子组件对齐方式
android:rowCount:设置网格布局行数
android:columnCount:设置网格布局列数
android:layout_row:设置该组件位于第几行
android:layout_columnL设置该组件位于第几列
AbsoluteLayout
绝对布局(过时)

约束布局

ConstraintLayout则是使用约束的方式来指定各个控件的位置和关系的,它有点类似于RelativeLayout,但远比RelativeLayout要更强大。
ConstraintLayout非常适合使用可视化方式编写界面(而不适合用XML书写),且ConstraintLayout可以有效地解决布局嵌套过多的问题(复杂的布局总会伴随着多层的嵌套,而嵌套越多,程序的性能也就越差)
Android新特性介绍:ConstraintLayout完全解析

LinearLayout,RelativeLayout性能对比

  1. 在不影响层级深度的情况下,使用LinearLayout和FrameLayout而不是RelativeLayout
    根据LinearLayout、FrameLayout和RelativeLayout的onMeasure()源码可分析得,相同层级下RelativeLayout性能最低:
  • RelativeLayout会让子View调用2次onMeasure
  • 若当前RelativeLayout布局的子View计算的高度与RelativeLayout布局不同,会引发效率问题
  1. 如果能用RelativeLayout减少LinearLayout布局的层级,则使用RelativeLayout
    采用尽量少的View层级来表达布局以实现性能最优,因为复杂的View嵌套对性能的影响会更大一些。
  2. LinearLayout慎用layout_weight
    LinearLayout 在有weight时,也会调用子View2次onMeasure

检测布局深度

  • Dump UI Hierarchy for UI Atomator,分析UI层级
  • HierachyViewer

布局优化

  • 布局优化思想
    减少Overdraw(过度绘制)(一般通过减少UI层级、简化布局实现)

Overdraw:描述的是屏幕上的某个像素在同一帧时间内被绘制了多次。在多层次的UI结构里面,如果不可见的UI也在做绘制的操作,就会导致某些像素区域被绘制了多次,浪费大量的CPU以及GPU资源。

  • 布局优化方法
  1. 善用相对布局RelativeLayout
    可以通过扁平的RelativeLayout降低LinearLayout嵌套所产生布局树的层级
  2. 使用抽象布局标签include、merge、ViewStub
  • < include />
    include标签常用于将布局中的公共部分提取出来
  • < merge />
    merge标签是作为include标签的一种辅助扩展来使用,它的主要作用是为了防止在引用布局文件时产生多余的布局嵌套(merge能够减少include可能产生的层级)
  • < ViewStub />
    ViewStub是View的子类。他是一个轻量级View, 隐藏的,没有尺寸的View。他可以用来在程序运行时简单的填充布局文件
  1. 使用Android最新的布局方式ConstaintLayout  
    ConstraintLayout允许你在不适用任何嵌套的情况下创建大型而又复杂的布局。它与RelativeLayout非常相似,所有的view都依赖于兄弟控件和父控件的相对关系。但是,ConstraintLayout比RelativeLayout更加灵活

include、merge、ViewStub标签

  • include
    include标签常用于将布局中的公共部分提取出来,解决重复定义布局的问题。
    下面是一个自定义的titlebar文件:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="wrap_content"    android:background="@color/titlebar_bg">    <ImageView android:layout_width="wrap_content"               android:layout_height="wrap_content"               android:src="@drawable/gafricalogo" />FrameLayout>

在应用中使用titlebar布局文件,我们通过标签,布局文件如下:

<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/app_bg"    android:gravity="center_horizontal">    <include layout="@layout/titlebar"/>    <TextView android:layout_width="match_parent"              android:layout_height="wrap_content"              android:text="@string/hello"              android:padding="10dp" />    ...LinearLayout>
  • merge
    merge标签与include标签组合使用,可以有效减少View树的层次来优化布局
    一个线性布局中嵌套一个文本视图,主布局如下:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:id="@+id/layout_wrap"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical" >    <include        android:id="@+id/layout_import"        android:layout_width="match_parent"        android:layout_height="match_parent"        layout="@layout/include_text" />LinearLayout>

(1)单独使用include标签的嵌套布局,下面是嵌套布局的include_text.xml文件:

<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:id="@+id/textView"        android:layout_width="match_parent"        android:text="Hello World!"        android:layout_height="match_parent" />LinearLayout>

通过hierarchyviewer我们可以看到主布局View树的部分层级结构如下图:
第七章 布局_第1张图片
(2)merge与include标签组合使用的布局,下面是嵌套布局的include_text.xml文件:

<merge xmlns:android="http://schemas.android.com/apk/res/android" >    <TextView        android:id="@+id/textView"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:text="Hello World!"/>merge>

通过hierarchyviewer我们可以看到主布局View树的部分层级结构如下图:
第七章 布局_第2张图片
对比截图就可以发现上面的四层结构,现在已经是三层结构了。当我们使用标签的时候,系统会自动忽略merge层级,而把TextView直接放置与平级。

  • ViewStub
    ViewStub 标签实质上是一个宽高都为 0 的不可见 的轻量级View,占用资源非常小。可以通过延迟加载布局的方式优化布局提升渲染性能。适用于布局复杂却很少用的布局,如网络请求失败提示,列表为空提示,引导界面等。
    这里的延迟加载是指初始化时, 程序无需显示该标签所指向的布局文件(ViewStub 控件占用内存相比于其他控件很小)。 只有在特定的条件下(View.setVisibility(View.VISIBLE)或View.inflate()), 所指向的布局文件才需要被渲染, 且此布局文件直接将当前的 ViewStub 替换掉。

在开发过程中,经常会遇到这样一种情况,有些布局很复杂但是却很少使用。例如条目详情、进度条标识或者未读消息等,这些情况如果在一开始初始化,虽然设置可见性View.GONE,但是在Inflate的时候View仍然会被Inflate,仍然会创建对象,由于这些布局又相当复杂,所以会很消耗系统资源。

定义ViewStub布局文件

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:id="@+id/layout_wrap"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical" >    <ViewStub        android:id="@+id/stub_image"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:inflatedId="@+id/image_import"        android:layout="@layout/layout_image" />LinearLayout>

layout_image.xml文件如下

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="wrap_content"    android:id="@+id/layout_image">    <ImageView        android:id="@+id/imageView"        android:layout_width="match_parent"        android:layout_height="wrap_content" />LinearLayout>

加载ViewStub布局文件:
动态加载ViewStub所包含的布局文件有两种方式,方式一使用使用inflate()方法,方式二就是使用setVisibility(View.VISIBLE)。
ViewStub一旦visible/inflated,此时ViewStub所指向的布局文件(layout_image.xml)替换掉当前的ViewStub控件,它自己就不在是View试图层级的一部分了。所以后面无法再使用ViewStub来控制布局。

private ViewStub viewStub;protected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.layout_main2);    viewStub = (ViewStub) findViewById(R.id.stub_image);    //viewStub.inflate();//方式一    viewStub.setVisibility(View.VISIBLE);//方式二    ImageView imageView = (ImageView) findViewById(R.id.imageView);    imageView.setImageResource(R.drawable.image);}

示例View层级截图如下:
第七章 布局_第3张图片

面试

你知道布局文件到控件对象的过程吗?(Android布局文件映射源码分析)

布局文件映射两种方式 setContentView() inflate()
调用 setContentView(R.layout.main) View view = inflate.inflate(R.layout.main,null);
作用 将XML布局文件直接显示UI 将XML布局文件转换为一个View对象

更多相关文章

  1. Android 资源文件夹下的文件不能有大写字符,会导致R.java无法生成
  2. Android 5.0上动态布局层级覆盖问题
  3. Android自适应不同分辨率或不同屏幕大小的layout布局(横屏|竖屏)
  4. android的文件系统结构简单介绍
  5. 安卓课程六 android常用布局属性的介绍
  6. Android 约束布局(ConstraintLayout)的使用

随机推荐

  1. Android中Service和Activity相互通信示例
  2. Android音频和震动的基本实现
  3. Android入门进阶教程(16)-ActivityThead
  4. Android多分辨率适配-长度单位和转换计算
  5. 在BeagleBoard XM 开发板上运行Android
  6. 绗旇锛歓ygote鍜孲ystemServer杩涚▼鍚
  7. Android(安卓)解压zip文件(支持中文)
  8. Android(安卓)数据传输方式 WIFI 蓝牙 US
  9. Android系统架构图及简单的系统架构
  10. 内容提供器Content Providers